From 508bfa93c0b3de898aa76f5007088631ce02db24 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Mon, 13 Jun 2022 20:35:38 +0200 Subject: [PATCH 01/15] rotating_light: fix clippy warnings --- README.md | 4 ++-- feather/base/src/anvil/player.rs | 8 +++----- libcraft/items/src/item_stack.rs | 10 +++++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index aa6cfef37..99b37a98b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# Feather +# Feather + [![build](https://github.com/feather-rs/feather/workflows/build/badge.svg)](https://github.com/feather-rs/feather/actions) [![Discord](https://img.shields.io/discord/619316022800809995?logo=discord)](https://discordapp.com/invite/4eYmK69) - A Minecraft server implementation written in Rust. ### Status diff --git a/feather/base/src/anvil/player.rs b/feather/base/src/anvil/player.rs index 2e6100eda..798ffa9ed 100644 --- a/feather/base/src/anvil/player.rs +++ b/feather/base/src/anvil/player.rs @@ -72,16 +72,14 @@ pub struct InventorySlot { impl InventorySlot { /// Converts an [`ItemStack`] and network protocol index into an [`InventorySlot`]. pub fn from_network_index(network: usize, stack: &ItemStack) -> Option { - let slot = if SLOT_HOTBAR_OFFSET <= network && network < SLOT_HOTBAR_OFFSET + HOTBAR_SIZE { + let slot = if (SLOT_HOTBAR_OFFSET..SLOT_HOTBAR_OFFSET+HOTBAR_SIZE).contains(&network) { // Hotbar (network - SLOT_HOTBAR_OFFSET) as i8 } else if network == SLOT_OFFHAND { -106 - } else if SLOT_ARMOR_MIN <= network && network <= SLOT_ARMOR_MAX { + } else if (SLOT_ARMOR_MIN..SLOT_ARMOR_MAX).contains(&network) { ((SLOT_ARMOR_MAX - network) + 100) as i8 - } else if SLOT_INVENTORY_OFFSET <= network - && network < SLOT_INVENTORY_OFFSET + INVENTORY_SIZE - { + } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) { network as i8 } else { return None; diff --git a/libcraft/items/src/item_stack.rs b/libcraft/items/src/item_stack.rs index 067e0ac16..d1ec8b031 100644 --- a/libcraft/items/src/item_stack.rs +++ b/libcraft/items/src/item_stack.rs @@ -366,7 +366,15 @@ pub enum ItemStackError { impl Display for ItemStackError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self) + let name = match self { + ItemStackError::ClientOverflow => "Client overflow", + ItemStackError::EmptyStack => "Empty stack", + ItemStackError::ExceedsStackSize => "Exceeds stack size", + ItemStackError::IncompatibleStacks => "Incompatible stacks", + ItemStackError::NotEnoughItems => "Not enough items", + }; + + write!(f, "{}", name) } } From bdc2a80d8cb4630928675f20addf529d6712ff24 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Mon, 13 Jun 2022 22:07:21 +0200 Subject: [PATCH 02/15] rotating_light: rustfmt --- feather/base/src/anvil/player.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/feather/base/src/anvil/player.rs b/feather/base/src/anvil/player.rs index 798ffa9ed..02cc2e3d0 100644 --- a/feather/base/src/anvil/player.rs +++ b/feather/base/src/anvil/player.rs @@ -72,14 +72,15 @@ pub struct InventorySlot { impl InventorySlot { /// Converts an [`ItemStack`] and network protocol index into an [`InventorySlot`]. pub fn from_network_index(network: usize, stack: &ItemStack) -> Option { - let slot = if (SLOT_HOTBAR_OFFSET..SLOT_HOTBAR_OFFSET+HOTBAR_SIZE).contains(&network) { + let slot = if (SLOT_HOTBAR_OFFSET..SLOT_HOTBAR_OFFSET + HOTBAR_SIZE).contains(&network) { // Hotbar (network - SLOT_HOTBAR_OFFSET) as i8 } else if network == SLOT_OFFHAND { -106 } else if (SLOT_ARMOR_MIN..SLOT_ARMOR_MAX).contains(&network) { ((SLOT_ARMOR_MAX - network) + 100) as i8 - } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) { + } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) + { network as i8 } else { return None; From 8ab69a28f2d8d86ed1beaa281c50efc77769a605 Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Wed, 15 Jun 2022 08:20:36 +0200 Subject: [PATCH 03/15] Fix tests --- feather/base/src/anvil/player.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feather/base/src/anvil/player.rs b/feather/base/src/anvil/player.rs index 02cc2e3d0..cdaa27b19 100644 --- a/feather/base/src/anvil/player.rs +++ b/feather/base/src/anvil/player.rs @@ -72,12 +72,12 @@ pub struct InventorySlot { impl InventorySlot { /// Converts an [`ItemStack`] and network protocol index into an [`InventorySlot`]. pub fn from_network_index(network: usize, stack: &ItemStack) -> Option { - let slot = if (SLOT_HOTBAR_OFFSET..SLOT_HOTBAR_OFFSET + HOTBAR_SIZE).contains(&network) { + let slot = if (SLOT_HOTBAR_OFFSET..(SLOT_HOTBAR_OFFSET + HOTBAR_SIZE)).contains(&network) { // Hotbar (network - SLOT_HOTBAR_OFFSET) as i8 } else if network == SLOT_OFFHAND { -106 - } else if (SLOT_ARMOR_MIN..SLOT_ARMOR_MAX).contains(&network) { + } else if (SLOT_ARMOR_MIN..(SLOT_ARMOR_MAX+1)).contains(&network) { ((SLOT_ARMOR_MAX - network) + 100) as i8 } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) { From d14d82f83c9357fd786462849bc6de1283edbe36 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Wed, 15 Jun 2022 19:35:18 +0200 Subject: [PATCH 04/15] rotating_light: rustfmt 2 --- feather/base/src/anvil/player.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feather/base/src/anvil/player.rs b/feather/base/src/anvil/player.rs index cdaa27b19..45afa1475 100644 --- a/feather/base/src/anvil/player.rs +++ b/feather/base/src/anvil/player.rs @@ -77,7 +77,7 @@ impl InventorySlot { (network - SLOT_HOTBAR_OFFSET) as i8 } else if network == SLOT_OFFHAND { -106 - } else if (SLOT_ARMOR_MIN..(SLOT_ARMOR_MAX+1)).contains(&network) { + } else if (SLOT_ARMOR_MIN..(SLOT_ARMOR_MAX + 1)).contains(&network) { ((SLOT_ARMOR_MAX - network) + 100) as i8 } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) { From 6e54320e3eebb4fdf2406236ebba769b2054eb31 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Thu, 16 Jun 2022 10:50:18 +0200 Subject: [PATCH 05/15] sparkles: Begin Chat-Ansi Implementation --- Cargo.lock | 7 +++ feather/base/src/ansi.rs | 78 ++++++++++++++++++++++++++++++ feather/base/src/lib.rs | 1 + feather/server/src/systems/chat.rs | 15 +++++- libcraft/text/Cargo.toml | 1 + libcraft/text/src/text.rs | 41 ++++++++++++++++ 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 feather/base/src/ansi.rs diff --git a/Cargo.lock b/Cargo.lock index 0b4381092..84a8ecbf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1430,6 +1430,7 @@ dependencies = [ "serde", "serde_json", "serde_with", + "string-builder", "thiserror", "uuid", ] @@ -2769,6 +2770,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "string-builder" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd10a070fb1f2796a288abec42695db4682a82b6f12ffacd60fb8d5ad3a4a12" + [[package]] name = "strsim" version = "0.10.0" diff --git a/feather/base/src/ansi.rs b/feather/base/src/ansi.rs new file mode 100644 index 000000000..dac77aebd --- /dev/null +++ b/feather/base/src/ansi.rs @@ -0,0 +1,78 @@ +pub struct AnsiStyle { + format: u8, +} + +impl AnsiStyle { + pub fn regular() -> AnsiStyle { + AnsiStyle { format: 0 } + } + + pub fn bold() -> AnsiStyle { + AnsiStyle { format: 1 } + } + + pub fn underline() -> AnsiStyle { + AnsiStyle { format: 4 } + } + + fn format(&self, color: u8) -> String { format!("\033[{};{}m", self.format, color) } + + pub fn black(&self) -> String { self.format(30) } + + pub fn red(&self) -> String { self.format(31) } + + pub fn green(&self) -> String { self.format(32) } + + pub fn yellow(&self) -> String { self.format(33) } + + pub fn blue(&self) -> String { self.format(34) } + + pub fn magenta(&self) -> String { self.format(35) } + + pub fn cyan(&self) -> String { self.format(36) } + + pub fn white(&self) -> String { self.format(37) } + + pub fn reset(&self) -> &'static str { "\033[0m" } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ansi_style() { + let style = AnsiStyle::regular(); + assert_eq!(style.black(), "\033[0;30m"); + assert_eq!(style.red(), "\033[0;31m"); + assert_eq!(style.green(), "\033[0;32m"); + assert_eq!(style.yellow(), "\033[0;33m"); + assert_eq!(style.blue(), "\033[0;34m"); + assert_eq!(style.magenta(), "\033[0;35m"); + assert_eq!(style.cyan(), "\033[0;36m"); + assert_eq!(style.white(), "\033[0;37m"); + assert_eq!(style.reset(), "\033[0m"); + + let style = AnsiStyle::bold(); + assert_eq!(style.black(), "\033[1;30m"); + assert_eq!(style.red(), "\033[1;31m"); + assert_eq!(style.green(), "\033[1;32m"); + assert_eq!(style.yellow(), "\033[1;33m"); + assert_eq!(style.blue(), "\033[1;34m"); + assert_eq!(style.magenta(), "\033[1;35m"); + assert_eq!(style.cyan(), "\033[1;36m"); + assert_eq!(style.white(), "\033[1;37m"); + assert_eq!(style.reset(), "\033[0m"); + + let style = AnsiStyle::underline(); + assert_eq!(style.black(), "\033[4;30m"); + assert_eq!(style.red(), "\033[4;31m"); + assert_eq!(style.green(), "\033[4;32m"); + assert_eq!(style.yellow(), "\033[4;33m"); + assert_eq!(style.blue(), "\033[4;34m"); + assert_eq!(style.magenta(), "\033[4;35m"); + assert_eq!(style.cyan(), "\033[4;36m"); + assert_eq!(style.white(), "\033[4;37m"); + assert_eq!(style.reset(), "\033[0m"); + } +} \ No newline at end of file diff --git a/feather/base/src/lib.rs b/feather/base/src/lib.rs index 730d4c51a..5548e11e2 100644 --- a/feather/base/src/lib.rs +++ b/feather/base/src/lib.rs @@ -15,6 +15,7 @@ pub mod chunk; pub mod chunk_lock; pub mod inventory; pub mod metadata; +pub mod ansi; pub use block::{BlockPositionValidationError, ValidBlockPosition}; pub use blocks::*; diff --git a/feather/server/src/systems/chat.rs b/feather/server/src/systems/chat.rs index d19aa64ed..ca48d4a97 100644 --- a/feather/server/src/systems/chat.rs +++ b/feather/server/src/systems/chat.rs @@ -38,7 +38,7 @@ fn flush_console_chat_box(game: &mut Game) -> SysResult { for (_, (_console, mailbox)) in game.ecs.query::<(&Console, &mut ChatBox)>().iter() { for message in mailbox.drain() { // TODO: properly display chat message - log::info!("{:?}", message.text()); + log::info!("{:?}", message.text().as_ansi()); } } @@ -56,3 +56,16 @@ fn flush_title_chat_boxes(game: &mut Game, server: &mut Server) -> SysResult { Ok(()) } + +#[cfg(test)] +mod tests { + use base::Text; + + #[test] + fn test_ansi_text_serialization() { + let text = Text::from("Hello, world!"); + let ansi_text = text.as_ansi(); + println!("{} / {}", ansi_text, text); + assert_eq!(0, 1); + } +} \ No newline at end of file diff --git a/libcraft/text/Cargo.toml b/libcraft/text/Cargo.toml index b99bd785c..50b6f3e42 100644 --- a/libcraft/text/Cargo.toml +++ b/libcraft/text/Cargo.toml @@ -13,3 +13,4 @@ serde_json = "1" serde_with = "1" uuid = { version = "0.8", features = [ "serde" ] } thiserror = "1" +string-builder = "0.2.0" \ No newline at end of file diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index 90af776de..dd356522e 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -375,6 +375,23 @@ pub enum TextValue { }, } +impl TextValue{ + pub fn name_of(&self) -> &'static str { + match self { + TextValue::Text { .. } => "text", + TextValue::Translate { .. } => "translate", + TextValue::Score { .. } => "score", + TextValue::Selector { .. } => "selector", + TextValue::Keybind { .. } => "keybind", + TextValue::Nbt { .. } => "nbt", + } + } + + pub(crate) fn as_ansi(&self) -> String { + format!("", self.name_of()) // TODO + } +} + impl From for TextValue where T: Into>, @@ -966,6 +983,30 @@ impl Text { pub fn nbt>(nbt: A) -> Text { Text::from(TextValue::nbt(nbt)) } + + pub fn as_ansi(&self) -> String { + let mut ansi = string_builder::Builder::default(); + + let component = self.clone().into_component(); + let mut to_serialize: Vec = Vec::new(); + + to_serialize.push(component.value); + + if component.extra.is_some() { + for extra in component.extra.unwrap() { + to_serialize.push(extra.into_component().value); + } + } + + for value in to_serialize { + ansi.append(value.as_ansi()); + } + + ansi.string().expect(&*format!( + "Failed to convert text to ansi: {}", + &serde_json::to_string(self).unwrap() + )) + } } impl From for String { From 6b3d10725f93dcf9047de21639f2b0449291f34c Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Thu, 16 Jun 2022 11:03:42 +0200 Subject: [PATCH 06/15] reformat --- feather/base/src/ansi.rs | 42 ++++++++++++++++++++++-------- feather/base/src/lib.rs | 2 +- feather/server/src/systems/chat.rs | 2 +- libcraft/text/src/text.rs | 2 +- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/feather/base/src/ansi.rs b/feather/base/src/ansi.rs index dac77aebd..9e67afe4b 100644 --- a/feather/base/src/ansi.rs +++ b/feather/base/src/ansi.rs @@ -15,25 +15,45 @@ impl AnsiStyle { AnsiStyle { format: 4 } } - fn format(&self, color: u8) -> String { format!("\033[{};{}m", self.format, color) } + fn format(&self, color: u8) -> String { + format!("\033[{};{}m", self.format, color) + } - pub fn black(&self) -> String { self.format(30) } + pub fn black(&self) -> String { + self.format(30) + } - pub fn red(&self) -> String { self.format(31) } + pub fn red(&self) -> String { + self.format(31) + } - pub fn green(&self) -> String { self.format(32) } + pub fn green(&self) -> String { + self.format(32) + } - pub fn yellow(&self) -> String { self.format(33) } + pub fn yellow(&self) -> String { + self.format(33) + } - pub fn blue(&self) -> String { self.format(34) } + pub fn blue(&self) -> String { + self.format(34) + } - pub fn magenta(&self) -> String { self.format(35) } + pub fn magenta(&self) -> String { + self.format(35) + } - pub fn cyan(&self) -> String { self.format(36) } + pub fn cyan(&self) -> String { + self.format(36) + } - pub fn white(&self) -> String { self.format(37) } + pub fn white(&self) -> String { + self.format(37) + } - pub fn reset(&self) -> &'static str { "\033[0m" } + pub fn reset(&self) -> &'static str { + "\033[0m" + } } #[cfg(test)] @@ -75,4 +95,4 @@ mod tests { assert_eq!(style.white(), "\033[4;37m"); assert_eq!(style.reset(), "\033[0m"); } -} \ No newline at end of file +} diff --git a/feather/base/src/lib.rs b/feather/base/src/lib.rs index 5548e11e2..954d0e400 100644 --- a/feather/base/src/lib.rs +++ b/feather/base/src/lib.rs @@ -9,13 +9,13 @@ use std::time::Duration; use num_derive::{FromPrimitive, ToPrimitive}; use serde::{Deserialize, Serialize}; +pub mod ansi; pub mod anvil; mod block; pub mod chunk; pub mod chunk_lock; pub mod inventory; pub mod metadata; -pub mod ansi; pub use block::{BlockPositionValidationError, ValidBlockPosition}; pub use blocks::*; diff --git a/feather/server/src/systems/chat.rs b/feather/server/src/systems/chat.rs index ca48d4a97..827281bc7 100644 --- a/feather/server/src/systems/chat.rs +++ b/feather/server/src/systems/chat.rs @@ -68,4 +68,4 @@ mod tests { println!("{} / {}", ansi_text, text); assert_eq!(0, 1); } -} \ No newline at end of file +} diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index dd356522e..ab28aefbe 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -375,7 +375,7 @@ pub enum TextValue { }, } -impl TextValue{ +impl TextValue { pub fn name_of(&self) -> &'static str { match self { TextValue::Text { .. } => "text", From 3916d38b5af998e1adf2be233413ed48607996e3 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Thu, 16 Jun 2022 11:09:55 +0200 Subject: [PATCH 07/15] fix clippy warning --- libcraft/text/src/text.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index ab28aefbe..e570c09e9 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -988,9 +988,7 @@ impl Text { let mut ansi = string_builder::Builder::default(); let component = self.clone().into_component(); - let mut to_serialize: Vec = Vec::new(); - - to_serialize.push(component.value); + let mut to_serialize: Vec = vec![component.value]; if component.extra.is_some() { for extra in component.extra.unwrap() { From 0e902dad7d441cc3a18fad402ee44e311c023792 Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Thu, 16 Jun 2022 14:57:56 +0200 Subject: [PATCH 08/15] fix 29 clippy warnings, adding 20000 prob --- feather/base/src/ansi.rs | 58 ++++++++++++------------- quill/example-plugins/simple/src/lib.rs | 18 ++++---- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/feather/base/src/ansi.rs b/feather/base/src/ansi.rs index 9e67afe4b..ad37faaa7 100644 --- a/feather/base/src/ansi.rs +++ b/feather/base/src/ansi.rs @@ -16,7 +16,7 @@ impl AnsiStyle { } fn format(&self, color: u8) -> String { - format!("\033[{};{}m", self.format, color) + format!("\x1b[{};{}m", self.format, color) } pub fn black(&self) -> String { @@ -52,7 +52,7 @@ impl AnsiStyle { } pub fn reset(&self) -> &'static str { - "\033[0m" + "\x1b[0m" } } @@ -63,36 +63,36 @@ mod tests { #[test] fn test_ansi_style() { let style = AnsiStyle::regular(); - assert_eq!(style.black(), "\033[0;30m"); - assert_eq!(style.red(), "\033[0;31m"); - assert_eq!(style.green(), "\033[0;32m"); - assert_eq!(style.yellow(), "\033[0;33m"); - assert_eq!(style.blue(), "\033[0;34m"); - assert_eq!(style.magenta(), "\033[0;35m"); - assert_eq!(style.cyan(), "\033[0;36m"); - assert_eq!(style.white(), "\033[0;37m"); - assert_eq!(style.reset(), "\033[0m"); + assert_eq!(style.black(), "\x1b[0;30m"); + assert_eq!(style.red(), "\x1b[0;31m"); + assert_eq!(style.green(), "\x1b[0;32m"); + assert_eq!(style.yellow(), "\x1b[0;33m"); + assert_eq!(style.blue(), "\x1b[0;34m"); + assert_eq!(style.magenta(), "\x1b[0;35m"); + assert_eq!(style.cyan(), "\x1b[0;36m"); + assert_eq!(style.white(), "\x1b[0;37m"); + assert_eq!(style.reset(), "\x1b[0m"); let style = AnsiStyle::bold(); - assert_eq!(style.black(), "\033[1;30m"); - assert_eq!(style.red(), "\033[1;31m"); - assert_eq!(style.green(), "\033[1;32m"); - assert_eq!(style.yellow(), "\033[1;33m"); - assert_eq!(style.blue(), "\033[1;34m"); - assert_eq!(style.magenta(), "\033[1;35m"); - assert_eq!(style.cyan(), "\033[1;36m"); - assert_eq!(style.white(), "\033[1;37m"); - assert_eq!(style.reset(), "\033[0m"); + assert_eq!(style.black(), "\x1b[1;30m"); + assert_eq!(style.red(), "\x1b[1;31m"); + assert_eq!(style.green(), "\x1b[1;32m"); + assert_eq!(style.yellow(), "\x1b[1;33m"); + assert_eq!(style.blue(), "\x1b[1;34m"); + assert_eq!(style.magenta(), "\x1b[1;35m"); + assert_eq!(style.cyan(), "\x1b[1;36m"); + assert_eq!(style.white(), "\x1b[1;37m"); + assert_eq!(style.reset(), "\x1b[0m"); let style = AnsiStyle::underline(); - assert_eq!(style.black(), "\033[4;30m"); - assert_eq!(style.red(), "\033[4;31m"); - assert_eq!(style.green(), "\033[4;32m"); - assert_eq!(style.yellow(), "\033[4;33m"); - assert_eq!(style.blue(), "\033[4;34m"); - assert_eq!(style.magenta(), "\033[4;35m"); - assert_eq!(style.cyan(), "\033[4;36m"); - assert_eq!(style.white(), "\033[4;37m"); - assert_eq!(style.reset(), "\033[0m"); + assert_eq!(style.black(), "\x1b[4;30m"); + assert_eq!(style.red(), "\x1b[4;31m"); + assert_eq!(style.green(), "\x1b[4;32m"); + assert_eq!(style.yellow(), "\x1b[4;33m"); + assert_eq!(style.blue(), "\x1b[4;34m"); + assert_eq!(style.magenta(), "\x1b[4;35m"); + assert_eq!(style.cyan(), "\x1b[4;36m"); + assert_eq!(style.white(), "\x1b[4;37m"); + assert_eq!(style.reset(), "\x1b[0m"); } } diff --git a/quill/example-plugins/simple/src/lib.rs b/quill/example-plugins/simple/src/lib.rs index d6ac19dae..a76361d4d 100644 --- a/quill/example-plugins/simple/src/lib.rs +++ b/quill/example-plugins/simple/src/lib.rs @@ -23,14 +23,16 @@ fn test_system(plugin: &mut SimplePlugin, game: &mut Game) { for (entity, (position, name, gamemode, uuid)) in game.query::<(&Position, &Name, &Gamemode, &Uuid)>() { - entity.send_message(format!( - "[{}] Hi {}. Your gamemode is {:?} and your position is {:.1?} and your UUID is {}", - plugin.tick_counter, - name, - gamemode, - position, - uuid.to_hyphenated() - )); + if plugin.tick_counter % 50 == 0 { + entity.send_message(format!( + "[{}] Hi {}. Your gamemode is {:?} and your position is {:.1?} and your UUID is {}", + plugin.tick_counter, + name, + gamemode, + position, + uuid.to_hyphenated() + )); + } if plugin.tick_counter % 100 == 0 { entity.send_message("Spawning a mob on you"); From 26b84e690b3fa8883326fbcb62797ada36aef4bc Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 19:10:14 +0200 Subject: [PATCH 09/15] sparkles: finish component to ansi --- Cargo.lock | 11 + feather/base/src/lib.rs | 5 +- feather/protocol/src/packets/server/play.rs | 2 +- feather/server/Cargo.toml | 2 + feather/server/src/main.rs | 11 + feather/server/src/systems/chat.rs | 3 +- feather/server/src/systems/player_join.rs | 4 +- {feather/base => libcraft/text}/src/ansi.rs | 4 +- libcraft/text/src/lib.rs | 1 + libcraft/text/src/text.rs | 225 +++++++++++++++----- 10 files changed, 204 insertions(+), 64 deletions(-) rename {feather/base => libcraft/text}/src/ansi.rs (96%) diff --git a/Cargo.lock b/Cargo.lock index 84a8ecbf5..6e1986871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -713,6 +713,15 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "enable-ansi-support" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d29d3ca9ba14c336417f8d7bc7f373e8c16d10c30cc0794b09d3cecab631ab" +dependencies = [ + "winapi", +] + [[package]] name = "enumset" version = "1.0.8" @@ -939,6 +948,7 @@ dependencies = [ "base64ct", "colored", "crossbeam-utils", + "enable-ansi-support", "feather-base", "feather-common", "feather-ecs", @@ -953,6 +963,7 @@ dependencies = [ "hematite-nbt", "libcraft-core", "libcraft-items", + "libcraft-text", "log", "md-5", "num-bigint", diff --git a/feather/base/src/lib.rs b/feather/base/src/lib.rs index 954d0e400..d78e65c66 100644 --- a/feather/base/src/lib.rs +++ b/feather/base/src/lib.rs @@ -9,7 +9,6 @@ use std::time::Duration; use num_derive::{FromPrimitive, ToPrimitive}; use serde::{Deserialize, Serialize}; -pub mod ansi; pub mod anvil; mod block; pub mod chunk; @@ -19,12 +18,12 @@ pub mod metadata; pub use block::{BlockPositionValidationError, ValidBlockPosition}; pub use blocks::*; -pub use chunk::{Chunk, ChunkSection, CHUNK_HEIGHT, CHUNK_WIDTH}; +pub use chunk::{Chunk, CHUNK_HEIGHT, CHUNK_WIDTH, ChunkSection}; pub use chunk_lock::*; pub use libcraft_blocks::{BlockKind, BlockState}; pub use libcraft_core::{ - position, vec3, Biome, BlockPosition, ChunkPosition, EntityKind, Gamemode, Position, Vec3d, + Biome, BlockPosition, ChunkPosition, EntityKind, Gamemode, position, Position, vec3, Vec3d, }; pub use libcraft_inventory::{Area, Inventory}; pub use libcraft_items::{Item, ItemStack, ItemStackBuilder, ItemStackError}; diff --git a/feather/protocol/src/packets/server/play.rs b/feather/protocol/src/packets/server/play.rs index e52266b58..97f636f6e 100644 --- a/feather/protocol/src/packets/server/play.rs +++ b/feather/protocol/src/packets/server/play.rs @@ -370,7 +370,7 @@ pub enum GameStateChange { WinGame { show_credits: bool, }, - /// See https://help.minecraft.net/hc/en-us/articles/4408948974989-Minecraft-Java-Edition-Demo-Mode- + /// See DemoEvent(DemoEventType), /// Sent when any player is struck by an arrow. ArrowHitAnyPlayer, diff --git a/feather/server/Cargo.toml b/feather/server/Cargo.toml index 970560311..5aa655cf8 100644 --- a/feather/server/Cargo.toml +++ b/feather/server/Cargo.toml @@ -22,6 +22,7 @@ colored = "2" common = { path = "../common", package = "feather-common" } crossbeam-utils = "0.8" ecs = { path = "../ecs", package = "feather-ecs" } +enable-ansi-support = "0.1.2" fern = "0.6" flate2 = "1" flume = "0.10" @@ -55,6 +56,7 @@ uuid = "0.8" slab = "0.4" libcraft-core = { path = "../../libcraft/core" } libcraft-items = { path = "../../libcraft/items" } +libcraft-text = { path = "../../libcraft/text" } worldgen = { path = "../worldgen", package = "feather-worldgen" } [features] diff --git a/feather/server/src/main.rs b/feather/server/src/main.rs index c3bf7ea16..906a84056 100644 --- a/feather/server/src/main.rs +++ b/feather/server/src/main.rs @@ -15,6 +15,8 @@ const CONFIG_PATH: &str = "config.toml"; #[tokio::main] async fn main() -> anyhow::Result<()> { + enable_ansi(); + let feather_server::config::ConfigContainer { config, was_config_created, @@ -36,6 +38,15 @@ async fn main() -> anyhow::Result<()> { Ok(()) } +fn enable_ansi() { + match enable_ansi_support::enable_ansi_support() { + Ok(()) => {} + Err(_) => { + log::warn!("Failed to enable ANSI support, Output will not work properly"); + } + } +} + fn init_game(server: Server, config: &Config) -> anyhow::Result { let mut game = Game::new(); init_systems(&mut game, server); diff --git a/feather/server/src/systems/chat.rs b/feather/server/src/systems/chat.rs index 827281bc7..71ca23f81 100644 --- a/feather/server/src/systems/chat.rs +++ b/feather/server/src/systems/chat.rs @@ -37,8 +37,7 @@ fn flush_chat_boxes(game: &mut Game, server: &mut Server) -> SysResult { fn flush_console_chat_box(game: &mut Game) -> SysResult { for (_, (_console, mailbox)) in game.ecs.query::<(&Console, &mut ChatBox)>().iter() { for message in mailbox.drain() { - // TODO: properly display chat message - log::info!("{:?}", message.text().as_ansi()); + log::info!("{}", message.text().as_ansi().replace("\n", "")); } } diff --git a/feather/server/src/systems/player_join.rs b/feather/server/src/systems/player_join.rs index f8e01b195..311a01eb4 100644 --- a/feather/server/src/systems/player_join.rs +++ b/feather/server/src/systems/player_join.rs @@ -1,4 +1,5 @@ use libcraft_items::InventorySlot; +use libcraft_text::{IntoTextComponent, TextComponent, TextComponentBuilder}; use log::debug; use base::anvil::player::PlayerAbilities; @@ -143,7 +144,8 @@ fn accept_new_player(game: &mut Game, server: &mut Server, client_id: ClientId) fn broadcast_player_join(game: &mut Game, username: &str) { let message = Text::translate_with("multiplayer.player.joined", vec![username.to_owned()]); - game.broadcast_chat(ChatKind::System, message); + let mut component = message.into_component().yellow(); + game.broadcast_chat(ChatKind::System, component); } fn player_abilities_or_default( diff --git a/feather/base/src/ansi.rs b/libcraft/text/src/ansi.rs similarity index 96% rename from feather/base/src/ansi.rs rename to libcraft/text/src/ansi.rs index ad37faaa7..72b9c0cde 100644 --- a/feather/base/src/ansi.rs +++ b/libcraft/text/src/ansi.rs @@ -16,7 +16,7 @@ impl AnsiStyle { } fn format(&self, color: u8) -> String { - format!("\x1b[{};{}m", self.format, color) + format!("\x1B[{};{}m", self.format, color) } pub fn black(&self) -> String { @@ -51,7 +51,7 @@ impl AnsiStyle { self.format(37) } - pub fn reset(&self) -> &'static str { + pub fn reset() -> &'static str { "\x1b[0m" } } diff --git a/libcraft/text/src/lib.rs b/libcraft/text/src/lib.rs index 672851c8c..b6ae5b6fb 100644 --- a/libcraft/text/src/lib.rs +++ b/libcraft/text/src/lib.rs @@ -1,5 +1,6 @@ pub mod text; pub mod title; +pub mod ansi; pub use text::*; pub use title::Title; diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index e570c09e9..bc6c7e875 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -5,6 +5,7 @@ use std::borrow::Cow; use std::fmt::{self, Display, Formatter}; use std::str::FromStr; use uuid::Uuid; +use crate::ansi::AnsiStyle; pub mod markdown; @@ -146,10 +147,51 @@ impl From for Text { } } +impl From for String { + fn from(bind: Keybind) -> Self { + match bind { + Keybind::Attack => "attack".to_string(), + Keybind::UseItem => "use".to_string(), + Keybind::Forward => "forward".to_string(), + Keybind::Left => "left".to_string(), + Keybind::Back => "back".to_string(), + Keybind::Right => "right".to_string(), + Keybind::Jump => "jump".to_string(), + Keybind::Sneak => "sneak".to_string(), + Keybind::Sprint => "sprint".to_string(), + Keybind::Drop => "drop".to_string(), + Keybind::Inventory => "inventory".to_string(), + Keybind::Chat => "chat".to_string(), + Keybind::ListPlayers => "list_players".to_string(), + Keybind::PickBlock => "pick_block".to_string(), + Keybind::Command => "command".to_string(), + Keybind::Screenshot => "screenshot".to_string(), + Keybind::Perspective => "perspective".to_string(), + Keybind::MouseSmoothing => "mouse_smoothing".to_string(), + Keybind::Fullscreen => "fullscreen".to_string(), + Keybind::SpectatorOutlines => "spectator_outlines".to_string(), + Keybind::SwapHands => "swap_hands".to_string(), + Keybind::SaveToolbar => "save_toolbar".to_string(), + Keybind::LoadToolbar => "load_toolbar".to_string(), + Keybind::Advancements => "advancements".to_string(), + Keybind::Hotbar1 => "hotbar1".to_string(), + Keybind::Hotbar2 => "hotbar2".to_string(), + Keybind::Hotbar3 => "hotbar3".to_string(), + Keybind::Hotbar4 => "hotbar4".to_string(), + Keybind::Hotbar5 => "hotbar5".to_string(), + Keybind::Hotbar6 => "hotbar6".to_string(), + Keybind::Hotbar7 => "hotbar7".to_string(), + Keybind::Hotbar8 => "hotbar8".to_string(), + Keybind::Hotbar9 => "hotbar9".to_string(), + Keybind::Custom(s) => s.to_string() + } + } +} + impl Serialize for Keybind { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where + S: Serializer, { serializer.serialize_str(String::from(self).as_ref()) } @@ -157,8 +199,8 @@ impl Serialize for Keybind { impl<'de> Deserialize<'de> for Keybind { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(Keybind::from(s)) @@ -166,8 +208,8 @@ impl<'de> Deserialize<'de> for Keybind { } impl From for Keybind -where - T: Into>, + where + T: Into>, { fn from(keybind: T) -> Self { let keybind = keybind.into(); @@ -248,7 +290,7 @@ impl From<&Keybind> for String { Keybind::Hotbar9 => "key_key.hotbar.9", Keybind::Custom(bind) => bind.as_ref(), } - .into() + .into() } } @@ -260,10 +302,30 @@ pub enum Translate { Custom(Cow<'static, str>), } +impl Translate { + fn to_text(&self, args: &Vec, style: &String) -> String { + match self { + Translate::ChatTypeText => format!("<{}{}> {}", args[0].as_ansi(), style, args[1].as_ansi()), + Translate::MultiplayerPlayerJoined => format!("{}{} joined the game", args[0].as_ansi(), style), + Translate::Custom(name) => { + let mut args_strings: String = String::new(); + + for arg in args { + args_strings = format!("{} '{}{}'", args_strings, arg.as_ansi(), style); + } + + args_strings.push(' '); + + format!("", name, args_strings) + } + } + } +} + impl Serialize for Translate { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where + S: Serializer, { serializer.serialize_str(String::from(self).as_ref()) } @@ -271,8 +333,8 @@ impl Serialize for Translate { impl<'de> Deserialize<'de> for Translate { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(Translate::from(s)) @@ -280,9 +342,9 @@ impl<'de> Deserialize<'de> for Translate { } impl std::ops::Mul for Translate -where - T: IntoIterator, - T::Item: Into, + where + T: IntoIterator, + T::Item: Into, { type Output = Text; fn mul(self, rhs: T) -> Text { @@ -291,8 +353,8 @@ where } impl From for Translate -where - T: Into>, + where + T: Into>, { fn from(value: T) -> Translate { let value = value.into(); @@ -311,7 +373,7 @@ impl<'a> From<&Translate> for String { Translate::MultiplayerPlayerJoined => "multiplayer.player.joined", Translate::Custom(key) => key.as_ref(), } - .into() + .into() } } @@ -386,15 +448,11 @@ impl TextValue { TextValue::Nbt { .. } => "nbt", } } - - pub(crate) fn as_ansi(&self) -> String { - format!("", self.name_of()) // TODO - } } impl From for TextValue -where - T: Into>, + where + T: Into>, { fn from(value: T) -> Self { Self::text(value.into()) @@ -407,8 +465,8 @@ impl TextValue { } pub fn translate(translate: A) -> Self - where - A: Into, + where + A: Into, { TextValue::Translate { translate: translate.into(), @@ -417,10 +475,10 @@ impl TextValue { } pub fn translate_with(translate: A, with: B) -> Self - where - A: Into, - B: IntoIterator, - B::Item: Into, + where + A: Into, + B: IntoIterator, + B::Item: Into, { let with = with.into_iter().map(|e| e.into()).collect(); TextValue::Translate { @@ -490,6 +548,67 @@ impl TextComponent { pub fn empty() -> TextComponent { TextComponent::from("") } + + pub(crate) fn as_ansi(&self) -> String { + let mut style_type = AnsiStyle::regular(); + + if self.bold.unwrap_or(false) { + style_type = AnsiStyle::bold() + } + + if self.underlined.unwrap_or(false) { + style_type = AnsiStyle::underline() + } + + let mut style =style_type.white(); + + if self.color.is_some() { + let color = self.color.as_ref().unwrap(); + + match color { + Color::Black => style = style_type.black(), + Color::DarkGray => style = style_type.black(), + Color::White => style = style_type.white(), + Color::Gray => style = style_type.black(), + Color::Red => style = style_type.red(), + Color::DarkRed => style = style_type.red(), + Color::Gold => style = style_type.yellow(), + Color::Yellow => style = style_type.yellow(), + Color::DarkGreen => style = style_type.green(), + Color::Green => style = style_type.green(), + Color::Aqua => style = style_type.cyan(), + Color::DarkAqua => style = style_type.cyan(), + Color::DarkBlue => style = style_type.blue(), + Color::Blue => style = style_type.blue(), + Color::LightPurple => style = style_type.magenta(), + Color::DarkPurple => style = style_type.magenta(), + Color::Custom(_) => style = style_type.black(), + } + } + + + let content = if let TextValue::Text {text} = self.clone().value { + String::from(text) + } else if let TextValue::Translate {translate, with} = self.clone().value { + translate.to_text(&with, &style) + } else if let TextValue::Score {value, name, objective} = self.clone().value { + if value.is_some() { + format!("", name, objective, value.unwrap()) + } else { + format!("", objective, name) + } + } else if let TextValue::Selector {selector} = self.clone().value { + format!("{}", selector) + } else if let TextValue::Keybind {keybind} = self.clone().value { + format!("", String::from(keybind)) + } else if let TextValue::Nbt {nbt} = self.clone().value { + format!("", nbt) + } else { + panic!("Unsupported TextValue") + }; + + format!("{}{}{}", &style, content, AnsiStyle::reset()) + } } pub enum Reset { @@ -580,9 +699,9 @@ pub trait TextComponentBuilder { /// Inherited Text; they will inherent the parent's style, color, insertion, on_click, and on_hover. fn extra(self, extra: A) -> Self - where - A: IntoIterator, - A::Item: Into; + where + A: IntoIterator, + A::Item: Into; fn push_extra>(self, extra: A) -> Self; fn reset_extra(self) -> Self; @@ -601,8 +720,8 @@ impl IntoTextComponent for TextComponent { } impl TextComponentBuilder for T -where - T: IntoTextComponent + From, + where + T: IntoTextComponent + From, { fn set_style(self, style: Style, value: Option) -> Self { let mut component = self.into_component(); @@ -846,9 +965,9 @@ where } fn extra(self, extra: A) -> Self - where - A: IntoIterator, - A::Item: Into, + where + A: IntoIterator, + A::Item: Into, { let mut component = self.into_component(); component.extra = Some(extra.into_iter().map(|e| e.into()).collect()); @@ -897,8 +1016,8 @@ where } impl From for TextComponent -where - T: Into, + where + T: Into, { fn from(value: T) -> Self { TextComponent { @@ -956,10 +1075,10 @@ impl Text { } pub fn translate_with(translate: A, with: B) -> Self - where - A: Into, - B: IntoIterator, - B::Item: Into, + where + A: Into, + B: IntoIterator, + B::Item: Into, { Text::from(TextValue::translate_with(translate, with)) } @@ -988,18 +1107,14 @@ impl Text { let mut ansi = string_builder::Builder::default(); let component = self.clone().into_component(); - let mut to_serialize: Vec = vec![component.value]; + ansi.append(component.as_ansi()); if component.extra.is_some() { for extra in component.extra.unwrap() { - to_serialize.push(extra.into_component().value); + ansi.append(extra.as_ansi()); } } - for value in to_serialize { - ansi.append(value.as_ansi()); - } - ansi.string().expect(&*format!( "Failed to convert text to ansi: {}", &serde_json::to_string(self).unwrap() @@ -1032,8 +1147,8 @@ impl From for Text { } impl From for Text -where - T: Into>, + where + T: Into>, { fn from(value: T) -> Self { Text::String(value.into()) @@ -1063,8 +1178,8 @@ impl std::ops::Add for Text { /// A `Deserialize` impl for `Text` which uses the text markdown format. pub fn deserialize_text<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let string = String::deserialize(deserializer)?; @@ -1084,8 +1199,8 @@ impl From for String { } impl From for TextRoot -where - T: Into, + where + T: Into, { fn from(text: T) -> Self { match text.into() { From 2bc6db17589749b351983f1d01adc84967ac240a Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 19:23:45 +0200 Subject: [PATCH 10/15] sparkles: Add test and fix warnings --- feather/server/src/systems/chat.rs | 9 ++++----- feather/server/src/systems/player_join.rs | 4 ++-- libcraft/text/src/ansi.rs | 5 ++--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/feather/server/src/systems/chat.rs b/feather/server/src/systems/chat.rs index 71ca23f81..ddb9e73f9 100644 --- a/feather/server/src/systems/chat.rs +++ b/feather/server/src/systems/chat.rs @@ -37,7 +37,7 @@ fn flush_chat_boxes(game: &mut Game, server: &mut Server) -> SysResult { fn flush_console_chat_box(game: &mut Game) -> SysResult { for (_, (_console, mailbox)) in game.ecs.query::<(&Console, &mut ChatBox)>().iter() { for message in mailbox.drain() { - log::info!("{}", message.text().as_ansi().replace("\n", "")); + log::info!("{}", message.text().as_ansi()); } } @@ -58,13 +58,12 @@ fn flush_title_chat_boxes(game: &mut Game, server: &mut Server) -> SysResult { #[cfg(test)] mod tests { - use base::Text; + use libcraft_text::{TextComponent, TextComponentBuilder}; #[test] fn test_ansi_text_serialization() { - let text = Text::from("Hello, world!"); + let text = TextComponent::from("Hello, world!").red().bold(); let ansi_text = text.as_ansi(); - println!("{} / {}", ansi_text, text); - assert_eq!(0, 1); + assert_eq!("\x1b[1;31mHello, world!\x1b[0m", ansi_text); } } diff --git a/feather/server/src/systems/player_join.rs b/feather/server/src/systems/player_join.rs index 311a01eb4..9d7755632 100644 --- a/feather/server/src/systems/player_join.rs +++ b/feather/server/src/systems/player_join.rs @@ -1,5 +1,5 @@ use libcraft_items::InventorySlot; -use libcraft_text::{IntoTextComponent, TextComponent, TextComponentBuilder}; +use libcraft_text::{IntoTextComponent, TextComponentBuilder}; use log::debug; use base::anvil::player::PlayerAbilities; @@ -144,7 +144,7 @@ fn accept_new_player(game: &mut Game, server: &mut Server, client_id: ClientId) fn broadcast_player_join(game: &mut Game, username: &str) { let message = Text::translate_with("multiplayer.player.joined", vec![username.to_owned()]); - let mut component = message.into_component().yellow(); + let component = message.into_component().yellow(); game.broadcast_chat(ChatKind::System, component); } diff --git a/libcraft/text/src/ansi.rs b/libcraft/text/src/ansi.rs index 72b9c0cde..c5ddc4fba 100644 --- a/libcraft/text/src/ansi.rs +++ b/libcraft/text/src/ansi.rs @@ -62,6 +62,8 @@ mod tests { #[test] fn test_ansi_style() { + assert_eq!(AnsiStyle::reset(), "\x1b[0m"); + let style = AnsiStyle::regular(); assert_eq!(style.black(), "\x1b[0;30m"); assert_eq!(style.red(), "\x1b[0;31m"); @@ -71,7 +73,6 @@ mod tests { assert_eq!(style.magenta(), "\x1b[0;35m"); assert_eq!(style.cyan(), "\x1b[0;36m"); assert_eq!(style.white(), "\x1b[0;37m"); - assert_eq!(style.reset(), "\x1b[0m"); let style = AnsiStyle::bold(); assert_eq!(style.black(), "\x1b[1;30m"); @@ -82,7 +83,6 @@ mod tests { assert_eq!(style.magenta(), "\x1b[1;35m"); assert_eq!(style.cyan(), "\x1b[1;36m"); assert_eq!(style.white(), "\x1b[1;37m"); - assert_eq!(style.reset(), "\x1b[0m"); let style = AnsiStyle::underline(); assert_eq!(style.black(), "\x1b[4;30m"); @@ -93,6 +93,5 @@ mod tests { assert_eq!(style.magenta(), "\x1b[4;35m"); assert_eq!(style.cyan(), "\x1b[4;36m"); assert_eq!(style.white(), "\x1b[4;37m"); - assert_eq!(style.reset(), "\x1b[0m"); } } From 665fccee3dce8eb691f1905c8a0093ab7f51104c Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 19:25:56 +0200 Subject: [PATCH 11/15] rotating_light: fmt --- feather/base/src/lib.rs | 4 +- feather/server/src/main.rs | 2 +- libcraft/text/src/lib.rs | 2 +- libcraft/text/src/text.rs | 138 +++++++++++++++++++++---------------- 4 files changed, 81 insertions(+), 65 deletions(-) diff --git a/feather/base/src/lib.rs b/feather/base/src/lib.rs index d78e65c66..730d4c51a 100644 --- a/feather/base/src/lib.rs +++ b/feather/base/src/lib.rs @@ -18,12 +18,12 @@ pub mod metadata; pub use block::{BlockPositionValidationError, ValidBlockPosition}; pub use blocks::*; -pub use chunk::{Chunk, CHUNK_HEIGHT, CHUNK_WIDTH, ChunkSection}; +pub use chunk::{Chunk, ChunkSection, CHUNK_HEIGHT, CHUNK_WIDTH}; pub use chunk_lock::*; pub use libcraft_blocks::{BlockKind, BlockState}; pub use libcraft_core::{ - Biome, BlockPosition, ChunkPosition, EntityKind, Gamemode, position, Position, vec3, Vec3d, + position, vec3, Biome, BlockPosition, ChunkPosition, EntityKind, Gamemode, Position, Vec3d, }; pub use libcraft_inventory::{Area, Inventory}; pub use libcraft_items::{Item, ItemStack, ItemStackBuilder, ItemStackError}; diff --git a/feather/server/src/main.rs b/feather/server/src/main.rs index 906a84056..1b0f0eca5 100644 --- a/feather/server/src/main.rs +++ b/feather/server/src/main.rs @@ -16,7 +16,7 @@ const CONFIG_PATH: &str = "config.toml"; #[tokio::main] async fn main() -> anyhow::Result<()> { enable_ansi(); - + let feather_server::config::ConfigContainer { config, was_config_created, diff --git a/libcraft/text/src/lib.rs b/libcraft/text/src/lib.rs index b6ae5b6fb..e6493fc34 100644 --- a/libcraft/text/src/lib.rs +++ b/libcraft/text/src/lib.rs @@ -1,6 +1,6 @@ +pub mod ansi; pub mod text; pub mod title; -pub mod ansi; pub use text::*; pub use title::Title; diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index bc6c7e875..ea8d4619c 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -1,11 +1,11 @@ //! Implementation of the Minecraft chat component format. +use crate::ansi::AnsiStyle; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::fmt::{self, Display, Formatter}; use std::str::FromStr; use uuid::Uuid; -use crate::ansi::AnsiStyle; pub mod markdown; @@ -183,15 +183,15 @@ impl From for String { Keybind::Hotbar7 => "hotbar7".to_string(), Keybind::Hotbar8 => "hotbar8".to_string(), Keybind::Hotbar9 => "hotbar9".to_string(), - Keybind::Custom(s) => s.to_string() + Keybind::Custom(s) => s.to_string(), } } } impl Serialize for Keybind { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where + S: Serializer, { serializer.serialize_str(String::from(self).as_ref()) } @@ -199,8 +199,8 @@ impl Serialize for Keybind { impl<'de> Deserialize<'de> for Keybind { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(Keybind::from(s)) @@ -208,8 +208,8 @@ impl<'de> Deserialize<'de> for Keybind { } impl From for Keybind - where - T: Into>, +where + T: Into>, { fn from(keybind: T) -> Self { let keybind = keybind.into(); @@ -290,7 +290,7 @@ impl From<&Keybind> for String { Keybind::Hotbar9 => "key_key.hotbar.9", Keybind::Custom(bind) => bind.as_ref(), } - .into() + .into() } } @@ -303,10 +303,14 @@ pub enum Translate { } impl Translate { - fn to_text(&self, args: &Vec, style: &String) -> String { + fn to_text(&self, args: &[Text], style: &str) -> String { match self { - Translate::ChatTypeText => format!("<{}{}> {}", args[0].as_ansi(), style, args[1].as_ansi()), - Translate::MultiplayerPlayerJoined => format!("{}{} joined the game", args[0].as_ansi(), style), + Translate::ChatTypeText => { + format!("<{}{}> {}", args[0].as_ansi(), style, args[1].as_ansi()) + } + Translate::MultiplayerPlayerJoined => { + format!("{}{} joined the game", args[0].as_ansi(), style) + } Translate::Custom(name) => { let mut args_strings: String = String::new(); @@ -316,7 +320,10 @@ impl Translate { args_strings.push(' '); - format!("", name, args_strings) + format!( + "", + name, args_strings + ) } } } @@ -324,8 +331,8 @@ impl Translate { impl Serialize for Translate { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where + S: Serializer, { serializer.serialize_str(String::from(self).as_ref()) } @@ -333,8 +340,8 @@ impl Serialize for Translate { impl<'de> Deserialize<'de> for Translate { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(Translate::from(s)) @@ -342,9 +349,9 @@ impl<'de> Deserialize<'de> for Translate { } impl std::ops::Mul for Translate - where - T: IntoIterator, - T::Item: Into, +where + T: IntoIterator, + T::Item: Into, { type Output = Text; fn mul(self, rhs: T) -> Text { @@ -353,8 +360,8 @@ impl std::ops::Mul for Translate } impl From for Translate - where - T: Into>, +where + T: Into>, { fn from(value: T) -> Translate { let value = value.into(); @@ -373,7 +380,7 @@ impl<'a> From<&Translate> for String { Translate::MultiplayerPlayerJoined => "multiplayer.player.joined", Translate::Custom(key) => key.as_ref(), } - .into() + .into() } } @@ -451,8 +458,8 @@ impl TextValue { } impl From for TextValue - where - T: Into>, +where + T: Into>, { fn from(value: T) -> Self { Self::text(value.into()) @@ -465,8 +472,8 @@ impl TextValue { } pub fn translate(translate: A) -> Self - where - A: Into, + where + A: Into, { TextValue::Translate { translate: translate.into(), @@ -475,10 +482,10 @@ impl TextValue { } pub fn translate_with(translate: A, with: B) -> Self - where - A: Into, - B: IntoIterator, - B::Item: Into, + where + A: Into, + B: IntoIterator, + B::Item: Into, { let with = with.into_iter().map(|e| e.into()).collect(); TextValue::Translate { @@ -549,7 +556,7 @@ impl TextComponent { TextComponent::from("") } - pub(crate) fn as_ansi(&self) -> String { + pub fn as_ansi(&self) -> String { let mut style_type = AnsiStyle::regular(); if self.bold.unwrap_or(false) { @@ -560,7 +567,7 @@ impl TextComponent { style_type = AnsiStyle::underline() } - let mut style =style_type.white(); + let mut style = style_type.white(); if self.color.is_some() { let color = self.color.as_ref().unwrap(); @@ -586,22 +593,31 @@ impl TextComponent { } } - - let content = if let TextValue::Text {text} = self.clone().value { + let content = if let TextValue::Text { text } = self.clone().value { String::from(text) - } else if let TextValue::Translate {translate, with} = self.clone().value { + } else if let TextValue::Translate { translate, with } = self.clone().value { translate.to_text(&with, &style) - } else if let TextValue::Score {value, name, objective} = self.clone().value { + } else if let TextValue::Score { + value, + name, + objective, + } = self.clone().value + { if value.is_some() { - format!("", name, objective, value.unwrap()) + format!( + "", + name, + objective, + value.unwrap() + ) } else { format!("", objective, name) } - } else if let TextValue::Selector {selector} = self.clone().value { + } else if let TextValue::Selector { selector } = self.clone().value { format!("{}", selector) - } else if let TextValue::Keybind {keybind} = self.clone().value { + } else if let TextValue::Keybind { keybind } = self.clone().value { format!("", String::from(keybind)) - } else if let TextValue::Nbt {nbt} = self.clone().value { + } else if let TextValue::Nbt { nbt } = self.clone().value { format!("", nbt) } else { panic!("Unsupported TextValue") @@ -699,9 +715,9 @@ pub trait TextComponentBuilder { /// Inherited Text; they will inherent the parent's style, color, insertion, on_click, and on_hover. fn extra(self, extra: A) -> Self - where - A: IntoIterator, - A::Item: Into; + where + A: IntoIterator, + A::Item: Into; fn push_extra>(self, extra: A) -> Self; fn reset_extra(self) -> Self; @@ -720,8 +736,8 @@ impl IntoTextComponent for TextComponent { } impl TextComponentBuilder for T - where - T: IntoTextComponent + From, +where + T: IntoTextComponent + From, { fn set_style(self, style: Style, value: Option) -> Self { let mut component = self.into_component(); @@ -965,9 +981,9 @@ impl TextComponentBuilder for T } fn extra(self, extra: A) -> Self - where - A: IntoIterator, - A::Item: Into, + where + A: IntoIterator, + A::Item: Into, { let mut component = self.into_component(); component.extra = Some(extra.into_iter().map(|e| e.into()).collect()); @@ -1016,8 +1032,8 @@ impl TextComponentBuilder for T } impl From for TextComponent - where - T: Into, +where + T: Into, { fn from(value: T) -> Self { TextComponent { @@ -1075,10 +1091,10 @@ impl Text { } pub fn translate_with(translate: A, with: B) -> Self - where - A: Into, - B: IntoIterator, - B::Item: Into, + where + A: Into, + B: IntoIterator, + B::Item: Into, { Text::from(TextValue::translate_with(translate, with)) } @@ -1147,8 +1163,8 @@ impl From for Text { } impl From for Text - where - T: Into>, +where + T: Into>, { fn from(value: T) -> Self { Text::String(value.into()) @@ -1178,8 +1194,8 @@ impl std::ops::Add for Text { /// A `Deserialize` impl for `Text` which uses the text markdown format. pub fn deserialize_text<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, +where + D: Deserializer<'de>, { let string = String::deserialize(deserializer)?; @@ -1199,8 +1215,8 @@ impl From for String { } impl From for TextRoot - where - T: Into, +where + T: Into, { fn from(text: T) -> Self { match text.into() { From bcedda8f0c6a8fd7f6dc72a63b05d7c1c564f0e0 Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 19:46:30 +0200 Subject: [PATCH 12/15] sparkles: Add "multiplayer.player.left translation key" --- libcraft/text/src/text.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index ea8d4619c..b0d5bbcd4 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -299,6 +299,7 @@ impl From<&Keybind> for String { pub enum Translate { ChatTypeText, MultiplayerPlayerJoined, + MultiplayerPlayerLeft, Custom(Cow<'static, str>), } @@ -310,6 +311,9 @@ impl Translate { } Translate::MultiplayerPlayerJoined => { format!("{}{} joined the game", args[0].as_ansi(), style) + }, + Translate::MultiplayerPlayerLeft => { + format!("{}{} left the game", args[0].as_ansi(), style) } Translate::Custom(name) => { let mut args_strings: String = String::new(); @@ -368,6 +372,7 @@ where match value.as_ref() { "chat.type.text" => Translate::ChatTypeText, "multiplayer.player.joined" => Translate::MultiplayerPlayerJoined, + "multiplayer.player.left" => Translate::MultiplayerPlayerLeft, _ => Translate::Custom(value), } } @@ -378,6 +383,7 @@ impl<'a> From<&Translate> for String { match translate { Translate::ChatTypeText => "chat.type.text", Translate::MultiplayerPlayerJoined => "multiplayer.player.joined", + Translate::MultiplayerPlayerLeft => "multiplayer.player.left", Translate::Custom(key) => key.as_ref(), } .into() From 0e1444ec3776296bd72eeb62d9c6989c9d5e15dc Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 19:49:22 +0200 Subject: [PATCH 13/15] rotating_light: fmt --- libcraft/text/src/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcraft/text/src/text.rs b/libcraft/text/src/text.rs index b0d5bbcd4..3c3543bf3 100644 --- a/libcraft/text/src/text.rs +++ b/libcraft/text/src/text.rs @@ -311,7 +311,7 @@ impl Translate { } Translate::MultiplayerPlayerJoined => { format!("{}{} joined the game", args[0].as_ansi(), style) - }, + } Translate::MultiplayerPlayerLeft => { format!("{}{} left the game", args[0].as_ansi(), style) } From 96b344e88ba4f7c234e9bb9b8076030c943d4f6a Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 20:57:18 +0200 Subject: [PATCH 14/15] Revert unnessecary readme change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99b37a98b..c904c8a24 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Feather +# Feather [![build](https://github.com/feather-rs/feather/workflows/build/badge.svg)](https://github.com/feather-rs/feather/actions) [![Discord](https://img.shields.io/discord/619316022800809995?logo=discord)](https://discordapp.com/invite/4eYmK69) From 1d2f12d466621d0423a553d74570c660bc4244cf Mon Sep 17 00:00:00 2001 From: Bloeckchengrafik <37768199+Bloeckchengrafik@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:06:44 +0200 Subject: [PATCH 15/15] Revert Changes for Clippy `manual Range::contains implementation` --- feather/base/src/anvil/player.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/feather/base/src/anvil/player.rs b/feather/base/src/anvil/player.rs index 45afa1475..2e6100eda 100644 --- a/feather/base/src/anvil/player.rs +++ b/feather/base/src/anvil/player.rs @@ -72,14 +72,15 @@ pub struct InventorySlot { impl InventorySlot { /// Converts an [`ItemStack`] and network protocol index into an [`InventorySlot`]. pub fn from_network_index(network: usize, stack: &ItemStack) -> Option { - let slot = if (SLOT_HOTBAR_OFFSET..(SLOT_HOTBAR_OFFSET + HOTBAR_SIZE)).contains(&network) { + let slot = if SLOT_HOTBAR_OFFSET <= network && network < SLOT_HOTBAR_OFFSET + HOTBAR_SIZE { // Hotbar (network - SLOT_HOTBAR_OFFSET) as i8 } else if network == SLOT_OFFHAND { -106 - } else if (SLOT_ARMOR_MIN..(SLOT_ARMOR_MAX + 1)).contains(&network) { + } else if SLOT_ARMOR_MIN <= network && network <= SLOT_ARMOR_MAX { ((SLOT_ARMOR_MAX - network) + 100) as i8 - } else if (SLOT_INVENTORY_OFFSET..SLOT_INVENTORY_OFFSET + INVENTORY_SIZE).contains(&network) + } else if SLOT_INVENTORY_OFFSET <= network + && network < SLOT_INVENTORY_OFFSET + INVENTORY_SIZE { network as i8 } else {