mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
refactor: enchant command code refactor (#2768)
* refactor: enchant command
Removes the only_one var and nested logic
* chore: removed TODO since it is now patched
In commit 938a627 (fix(item): prevent stacking items with different components (#2624)) this is patched since if a item is enchanted it will always have a extra data component which will now be detected and synced
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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::<EnchantmentsImpl>() {
|
||||
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<i32> {
|
||||
.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<dyn EntityBase>,
|
||||
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::<EnchantmentsImpl>()
|
||||
&& !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(
|
||||
|
||||
Reference in New Issue
Block a user