mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Changed bossbar title to TextComponent instead of String (#435)
* Changed bossbar title to TextComponent instead of String * Clippy and fmt
This commit is contained in:
81
pumpkin/src/command/args/arg_textcomponent.rs
Normal file
81
pumpkin/src/command/args/arg_textcomponent.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use crate::command::args::{Arg, ArgumentConsumer, FindArg, GetClientSideArgParser};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
use crate::command::tree::RawArgs;
|
||||
use crate::command::CommandSender;
|
||||
use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use pumpkin_protocol::client::play::{
|
||||
CommandSuggestion, ProtoCmdArgParser, ProtoCmdArgSuggestionType,
|
||||
};
|
||||
|
||||
pub(crate) struct TextComponentArgConsumer;
|
||||
|
||||
impl GetClientSideArgParser for TextComponentArgConsumer {
|
||||
fn get_client_side_parser(&self) -> ProtoCmdArgParser {
|
||||
ProtoCmdArgParser::Component
|
||||
}
|
||||
|
||||
fn get_client_side_suggestion_type_override(&self) -> Option<ProtoCmdArgSuggestionType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ArgumentConsumer for TextComponentArgConsumer {
|
||||
async fn consume<'a>(
|
||||
&'a self,
|
||||
_sender: &CommandSender<'a>,
|
||||
_server: &'a Server,
|
||||
args: &mut RawArgs<'a>,
|
||||
) -> Option<Arg<'a>> {
|
||||
let s = args.pop()?;
|
||||
|
||||
let text_component = parse_text_component(s);
|
||||
|
||||
let Some(text_component) = text_component else {
|
||||
if s.starts_with('"') && s.ends_with('"') {
|
||||
let s = s.replace('"', "");
|
||||
return Some(Arg::TextComponent(TextComponent::text(s)));
|
||||
}
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(Arg::TextComponent(text_component))
|
||||
}
|
||||
|
||||
async fn suggest<'a>(
|
||||
&'a self,
|
||||
_sender: &CommandSender<'a>,
|
||||
_server: &'a Server,
|
||||
_input: &'a str,
|
||||
) -> Result<Option<Vec<CommandSuggestion>>, CommandError> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl FindArg<'_> for TextComponentArgConsumer {
|
||||
type Data = TextComponent;
|
||||
|
||||
fn find_arg(args: &super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::TextComponent(data)) => Ok(data.clone()),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_text_component(input: &str) -> Option<TextComponent> {
|
||||
if input.starts_with('[') && input.ends_with(']') {
|
||||
let text_component_array: Option<Vec<TextComponent>> =
|
||||
serde_json::from_str(input).unwrap_or(None);
|
||||
let mut text_component_array = text_component_array?;
|
||||
let mut constructed_text_component = text_component_array[0].clone();
|
||||
text_component_array.remove(0);
|
||||
constructed_text_component.extra = text_component_array;
|
||||
|
||||
Some(constructed_text_component)
|
||||
} else {
|
||||
serde_json::from_str(input).unwrap_or(None)
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ use std::{collections::HashMap, hash::Hash, sync::Arc};
|
||||
|
||||
use arg_bounded_num::{NotInBounds, Number};
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use pumpkin_core::{
|
||||
math::{position::WorldPosition, vector2::Vector2, vector3::Vector3},
|
||||
GameMode,
|
||||
@@ -36,6 +37,7 @@ pub(crate) mod arg_position_block;
|
||||
pub(crate) mod arg_resource_location;
|
||||
pub(crate) mod arg_rotation;
|
||||
pub(crate) mod arg_simple;
|
||||
pub(crate) mod arg_textcomponent;
|
||||
mod coordinate;
|
||||
|
||||
/// see [`crate::commands::tree_builder::argument`]
|
||||
@@ -87,6 +89,7 @@ pub(crate) enum Arg<'a> {
|
||||
BossbarColor(BossbarColor),
|
||||
BossbarStyle(BossbarDivisions),
|
||||
Msg(String),
|
||||
TextComponent(TextComponent),
|
||||
Num(Result<Number, NotInBounds>),
|
||||
Bool(bool),
|
||||
#[allow(unused)]
|
||||
|
||||
@@ -4,12 +4,11 @@ use crate::command::args::arg_bossbar_style::BossbarStyleArgumentConsumer;
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::arg_resource_location::ResourceLocationArgumentConsumer;
|
||||
use crate::command::args::arg_simple::SimpleArgConsumer;
|
||||
use crate::command::args::{
|
||||
Arg, ConsumedArgs, DefaultNameArgConsumer, FindArg, FindArgDefaultName,
|
||||
};
|
||||
|
||||
use crate::command::args::{ConsumedArgs, DefaultNameArgConsumer, FindArg, FindArgDefaultName};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
use crate::command::dispatcher::CommandError::InvalidConsumption;
|
||||
|
||||
use crate::command::args::arg_textcomponent::TextComponentArgConsumer;
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, argument_default_name, literal};
|
||||
use crate::command::{CommandExecutor, CommandSender};
|
||||
@@ -55,7 +54,6 @@ enum CommandValueSet {
|
||||
struct BossbarAddExecuter;
|
||||
|
||||
#[async_trait]
|
||||
#[expect(clippy::inefficient_to_string)]
|
||||
impl CommandExecutor for BossbarAddExecuter {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
@@ -64,9 +62,7 @@ impl CommandExecutor for BossbarAddExecuter {
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let namespace = non_autocomplete_consumer().find_arg_default_name(args)?;
|
||||
let Some(Arg::Simple(name)) = args.get(ARG_NAME) else {
|
||||
return Err(InvalidConsumption(Some(ARG_NAME.into())));
|
||||
};
|
||||
let text_component = TextComponentArgConsumer::find_arg(args, ARG_NAME)?;
|
||||
|
||||
if server.bossbars.lock().await.has_bossbar(namespace) {
|
||||
send_error_message(
|
||||
@@ -77,13 +73,21 @@ impl CommandExecutor for BossbarAddExecuter {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let bossbar = Bossbar::new(name.to_string());
|
||||
let bossbar = Bossbar::new(text_component);
|
||||
server
|
||||
.bossbars
|
||||
.lock()
|
||||
.await
|
||||
.create_bossbar(namespace.to_string(), bossbar.clone());
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
TextComponent::text("Created custom bossbar [")
|
||||
.add_child(bossbar.title)
|
||||
.add_child(TextComponent::text("]")),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -111,36 +115,30 @@ impl CommandExecutor for BossbarGetExecuter {
|
||||
|
||||
match self.0 {
|
||||
CommandValueGet::Max => {
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has a maximum of {}",
|
||||
bossbar.bossbar_data.title, bossbar.max
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("has a maximum of {}", bossbar.max),
|
||||
)
|
||||
.await;
|
||||
return Ok(());
|
||||
}
|
||||
CommandValueGet::Players => {}
|
||||
CommandValueGet::Value => {
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has a value of {}",
|
||||
bossbar.bossbar_data.title, bossbar.value
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("has a value of {}", bossbar.value),
|
||||
)
|
||||
.await;
|
||||
return Ok(());
|
||||
}
|
||||
CommandValueGet::Visible => {
|
||||
let state = if bossbar.visible { "shown" } else { "hidden" };
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] is currently {state}",
|
||||
bossbar.bossbar_data.title
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("is currently {state}"),
|
||||
)
|
||||
.await;
|
||||
return Ok(());
|
||||
@@ -167,24 +165,25 @@ impl CommandExecutor for BossbarListExecuter {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let mut bossbars_string = String::new();
|
||||
let mut bossbars_text = TextComponent::text(format!(
|
||||
"There are {} custom bossbar(s) active: ",
|
||||
bossbars.len()
|
||||
));
|
||||
for (i, bossbar) in bossbars.iter().enumerate() {
|
||||
if i == 0 {
|
||||
bossbars_string += format!("[{}]", bossbar.bossbar_data.title).as_str();
|
||||
bossbars_text = bossbars_text
|
||||
.add_child(TextComponent::text("["))
|
||||
.add_child(bossbar.bossbar_data.title.clone())
|
||||
.add_child(TextComponent::text("]"));
|
||||
} else {
|
||||
bossbars_string += format!(", [{}]", bossbar.bossbar_data.title).as_str();
|
||||
bossbars_text = bossbars_text
|
||||
.add_child(TextComponent::text(", ["))
|
||||
.add_child(bossbar.bossbar_data.title.clone())
|
||||
.add_child(TextComponent::text("]"));
|
||||
}
|
||||
}
|
||||
|
||||
send_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"There are {} custom bossbar(s) active: {}",
|
||||
bossbars.len(),
|
||||
bossbars_string
|
||||
),
|
||||
)
|
||||
.await;
|
||||
sender.send_message(bossbars_text).await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -266,12 +265,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has changed color",
|
||||
bossbar.bossbar_data.title
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
String::from("has changed color"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
@@ -305,25 +302,21 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has changed maximum to {}",
|
||||
bossbar.bossbar_data.title, max_value
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("has changed maximum to {max_value}"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
CommandValueSet::Name => {
|
||||
let Some(Arg::Simple(name)) = args.get(ARG_NAME) else {
|
||||
return Err(InvalidConsumption(Some(ARG_NAME.into())));
|
||||
};
|
||||
let text_component = TextComponentArgConsumer::find_arg(args, ARG_NAME)?;
|
||||
match server
|
||||
.bossbars
|
||||
.lock()
|
||||
.await
|
||||
.update_name(server, namespace, name)
|
||||
.update_name(server, namespace, text_component.clone())
|
||||
.await
|
||||
{
|
||||
Ok(()) => {}
|
||||
@@ -333,8 +326,12 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
send_success_message(sender, format!("Custom bossbar [{name}] has been renamed"))
|
||||
.await;
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
text_component,
|
||||
String::from("has been renamed"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
CommandValueSet::Players(has_players) => {
|
||||
@@ -352,12 +349,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] no longer has any players",
|
||||
bossbar.bossbar_data.title
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
String::from("no longer has any players"),
|
||||
)
|
||||
.await;
|
||||
return Ok(());
|
||||
@@ -388,13 +383,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
.map(|player| player.gameprofile.name.clone())
|
||||
.collect();
|
||||
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] now has {count} player(s): {}",
|
||||
bossbar.bossbar_data.title,
|
||||
player_names.join(", ")
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("now has {count} player(s): {}", player_names.join(", ")),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
@@ -414,12 +406,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has changed style",
|
||||
bossbar.bossbar_data.title
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
String::from("has changed style"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
@@ -448,12 +438,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] has changed value to {}",
|
||||
bossbar.bossbar_data.title, value
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("changed value to {value}"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
@@ -476,12 +464,10 @@ impl CommandExecutor for BossbarSetExecuter {
|
||||
}
|
||||
|
||||
let state = if visibility { "visible" } else { "hidden" };
|
||||
send_success_message(
|
||||
send_prefix_success_message(
|
||||
sender,
|
||||
format!(
|
||||
"Custom bossbar [{}] is now {state}",
|
||||
bossbar.bossbar_data.title
|
||||
),
|
||||
bossbar.bossbar_data.title,
|
||||
format!("is now {state}"),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
@@ -500,12 +486,11 @@ fn value_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(
|
||||
literal("add").with_child(
|
||||
argument_default_name(non_autocomplete_consumer())
|
||||
.with_child(argument(ARG_NAME, SimpleArgConsumer).execute(BossbarAddExecuter)),
|
||||
.with_child(literal("add").with_child(
|
||||
argument_default_name(non_autocomplete_consumer()).with_child(
|
||||
argument(ARG_NAME, TextComponentArgConsumer).execute(BossbarAddExecuter),
|
||||
),
|
||||
)
|
||||
))
|
||||
.with_child(
|
||||
literal("get").with_child(
|
||||
argument_default_name(autocomplete_consumer())
|
||||
@@ -542,7 +527,7 @@ pub fn init_command_tree() -> CommandTree {
|
||||
)
|
||||
.with_child(
|
||||
literal("name").with_child(
|
||||
argument(ARG_NAME, SimpleArgConsumer)
|
||||
argument(ARG_NAME, TextComponentArgConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Name)),
|
||||
),
|
||||
)
|
||||
@@ -576,6 +561,21 @@ pub fn init_command_tree() -> CommandTree {
|
||||
)
|
||||
}
|
||||
|
||||
fn bossbar_prefix(title: TextComponent, trailing: &str) -> TextComponent {
|
||||
TextComponent::text("Custom bossbar [")
|
||||
.add_child(title)
|
||||
.add_child(TextComponent::text(format!("] {trailing}")))
|
||||
}
|
||||
|
||||
async fn send_prefix_success_message(
|
||||
sender: &CommandSender<'_>,
|
||||
title: TextComponent,
|
||||
message: String,
|
||||
) {
|
||||
sender
|
||||
.send_message(bossbar_prefix(title, message.as_str()))
|
||||
.await;
|
||||
}
|
||||
async fn send_success_message(sender: &CommandSender<'_>, message: String) {
|
||||
sender.send_message(TextComponent::text(message)).await;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ pub enum BossbarFlags {
|
||||
#[derive(Clone)]
|
||||
pub struct Bossbar {
|
||||
pub uuid: Uuid,
|
||||
pub title: String,
|
||||
pub title: TextComponent,
|
||||
pub health: f32,
|
||||
pub color: BossbarColor,
|
||||
pub division: BossbarDivisions,
|
||||
@@ -43,7 +43,7 @@ pub struct Bossbar {
|
||||
|
||||
impl Bossbar {
|
||||
#[must_use]
|
||||
pub fn new(title: String) -> Self {
|
||||
pub fn new(title: TextComponent) -> Self {
|
||||
let uuid = Uuid::new_v4();
|
||||
|
||||
Self {
|
||||
@@ -63,7 +63,7 @@ impl Player {
|
||||
// Maybe this section could be implemented. feel free to change
|
||||
let bossbar = bossbar.clone();
|
||||
let boss_action = BosseventAction::Add {
|
||||
title: TextComponent::text(bossbar.title),
|
||||
title: bossbar.title,
|
||||
health: bossbar.health,
|
||||
color: (bossbar.color as u8).into(),
|
||||
division: (bossbar.division as u8).into(),
|
||||
@@ -87,8 +87,8 @@ impl Player {
|
||||
self.client.send_packet(&packet).await;
|
||||
}
|
||||
|
||||
pub async fn update_bossbar_title(&self, uuid: &Uuid, title: String) {
|
||||
let boss_action = BosseventAction::UpdateTile(TextComponent::text(title));
|
||||
pub async fn update_bossbar_title(&self, uuid: &Uuid, title: TextComponent) {
|
||||
let boss_action = BosseventAction::UpdateTile(title);
|
||||
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
self.client.send_packet(&packet).await;
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::command::args::GetCloned;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::bossbar::{Bossbar, BossbarColor, BossbarDivisions};
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
@@ -236,7 +237,7 @@ impl CustomBossbars {
|
||||
&mut self,
|
||||
server: &Server,
|
||||
resource_location: &str,
|
||||
new_title: &str,
|
||||
new_title: TextComponent,
|
||||
) -> Result<(), BossbarUpdateError> {
|
||||
let bossbar = self.custom_bossbars.get_mut(resource_location);
|
||||
if let Some(bossbar) = bossbar {
|
||||
@@ -246,7 +247,7 @@ impl CustomBossbars {
|
||||
)));
|
||||
}
|
||||
|
||||
bossbar.bossbar_data.title = new_title.to_string();
|
||||
bossbar.bossbar_data.title = new_title;
|
||||
|
||||
if !bossbar.visible {
|
||||
return Ok(());
|
||||
|
||||
Reference in New Issue
Block a user