diff --git a/pumpkin-data/src/item_stack/mod.rs b/pumpkin-data/src/item_stack/mod.rs index 481237f3c..f0f6ecd49 100644 --- a/pumpkin-data/src/item_stack/mod.rs +++ b/pumpkin-data/src/item_stack/mod.rs @@ -547,7 +547,6 @@ impl ItemStack { } pub fn enchant(&mut self, enchantment: &'static Enchantment, level: i32) { - // TODO itemstack may not send update packet to client if level <= 0 { return; } diff --git a/pumpkin/src/command/commands/enchant.rs b/pumpkin/src/command/commands/enchant.rs index 0f9d33cb1..4db8ba969 100644 --- a/pumpkin/src/command/commands/enchant.rs +++ b/pumpkin/src/command/commands/enchant.rs @@ -1,5 +1,6 @@ -use pumpkin_data::translation; +use pumpkin_data::{Enchantment, translation}; use pumpkin_util::text::TextComponent; +use std::sync::Arc; use crate::command::args::bounded_num::{BoundedNumArgumentConsumer, NotInBounds}; use crate::command::args::entities::EntitiesArgumentConsumer; @@ -8,6 +9,7 @@ use crate::command::args::{ConsumedArgs, FindArgDefaultName}; use crate::command::tree::CommandTree; use crate::command::tree::builder::argument_default_name; use crate::command::{CommandError, CommandExecutor, CommandResult, CommandSender}; +use crate::entity::EntityBase; use pumpkin_data::data_component_impl::EnchantmentsImpl; const NAMES: [&str; 1] = ["enchant"]; @@ -16,7 +18,6 @@ const DESCRIPTION: &str = "Adds an enchantment to a player's selected item, subj struct Executor; impl CommandExecutor for Executor { - #[expect(clippy::too_many_lines)] fn execute<'a>( &'a self, sender: &'a CommandSender, @@ -65,94 +66,46 @@ impl CommandExecutor for Executor { return Err(CommandError::CommandFailed(msg)); } - let only_one = targets.len() == 1; - let mut success = 0; + let mut successful_targets = 0; + + if targets.len() == 1 { + return match enchant_target(&targets[0], enchantment, level).await { + Ok(()) => { + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_SUCCESS_SINGLE, + translation::bedrock::COMMANDS_ENCHANT_SUCCESS, + [ + enchantment.get_fullname(level), + targets[0].get_display_name().await, + ], + ); + sender.send_message(msg).await; + Ok(1) + } + Err(e) => Err(e), + }; + } for target in targets { - // let Some(target) = target.get_living_entity() else { - // if only_one { - // let msg = TextComponent::translate_cross(// "commands.enchant.failed.entity".clone(), // "commands.enchant.failed.entity", // [targets[0].get_display_name().await], - // ); - // sender.send_message(msg).await; - // return Ok(()); - // } - // continue; - // }; - // let lock = target.entity_equipment.lock().await.get(&EquipmentSlot::MAIN_HAND); TODO this dont work - let Some(player) = target.get_player() else { - continue; - }; - let lock = player.inventory.held_item(); - let mut item = lock.lock().await; - if item.is_empty() { - if only_one { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_FAILED_ITEMLESS, - translation::bedrock::COMMANDS_ENCHANT_NOITEM, - [targets[0].get_display_name().await], - ); - return Err(CommandError::CommandFailed(msg)); - } - continue; - } - if !enchantment.can_enchant(item.item) { - if only_one { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_FAILED_INCOMPATIBLE, - translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, - [item.item.translated_name()], - ); - return Err(CommandError::CommandFailed(msg)); - } - continue; - } - if let Some(data) = item.get_data_component::() { - if enchantment.is_enchantment_compatible(data) { - item.enchant(enchantment, level); - success += 1; - } else if only_one { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_FAILED_INCOMPATIBLE, - translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, - [item.item.translated_name()], - ); - return Err(CommandError::CommandFailed(msg)); - } - } else { - item.enchant(enchantment, level); - success += 1; + if enchant_target(target, enchantment, level).await.is_ok() { + successful_targets += 1; } } - if success == 0 { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_FAILED, - translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, - [TextComponent::text("")], - ); - return Err(CommandError::CommandFailed(msg)); + + if successful_targets == 0 { + return Err(commands_enchant_failed()); } - if only_one { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_SUCCESS_SINGLE, - translation::bedrock::COMMANDS_ENCHANT_SUCCESS, - [ - enchantment.get_fullname(level), - targets[0].get_display_name().await, - ], - ); - sender.send_message(msg).await; - } else { - let msg = TextComponent::translate_cross( - translation::java::COMMANDS_ENCHANT_SUCCESS_MULTIPLE, - translation::bedrock::COMMANDS_ENCHANT_SUCCESS, - [ - enchantment.get_fullname(level), - TextComponent::text(targets.len().to_string()), - ], - ); - sender.send_message(msg).await; - } - Ok(success) + + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_SUCCESS_MULTIPLE, + translation::bedrock::COMMANDS_ENCHANT_SUCCESS, + [ + enchantment.get_fullname(level), + TextComponent::text(targets.len().to_string()), + ], + ); + sender.send_message(msg).await; + Ok(successful_targets) }) } } @@ -164,6 +117,60 @@ const fn enchantment_level_consumer() -> BoundedNumArgumentConsumer { .max(i32::MAX) } +fn commands_enchant_failed() -> CommandError { + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_FAILED, + translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, + [TextComponent::text("")], + ); + CommandError::CommandFailed(msg) +} + +async fn enchant_target( + target: &Arc, + enchantment: &'static Enchantment, + level: i32, +) -> Result<(), CommandError> { + let Some(player) = target.get_player() else { + return Err(commands_enchant_failed()); + }; + + let lock = player.inventory.held_item(); + let mut item = lock.lock().await; + + if item.is_empty() { + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_FAILED_ITEMLESS, + translation::bedrock::COMMANDS_ENCHANT_NOITEM, + [target.get_display_name().await], + ); + return Err(CommandError::CommandFailed(msg)); + } + + if !enchantment.can_enchant(item.item) { + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_FAILED_INCOMPATIBLE, + translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, + [item.item.translated_name()], + ); + return Err(CommandError::CommandFailed(msg)); + } + + if let Some(data) = item.get_data_component::() + && !enchantment.is_enchantment_compatible(data) + { + let msg = TextComponent::translate_cross( + translation::java::COMMANDS_ENCHANT_FAILED_INCOMPATIBLE, + translation::bedrock::COMMANDS_ENCHANT_CANTENCHANT, + [item.item.translated_name()], + ); + return Err(CommandError::CommandFailed(msg)); + } + + item.enchant(enchantment, level); + Ok(()) +} + pub fn init_command_tree() -> CommandTree { CommandTree::new(NAMES, DESCRIPTION).then( argument_default_name(EntitiesArgumentConsumer).then(