steel_core/command/builtins/
damage.rs1use std::sync::Arc;
4
5use super::super::{
6 brigadier::{ArgumentType, CommandNodeBuilder, CommandSyntaxError},
7 execution::{
8 CommandSource, SteelArgumentType, SteelCommandContext, SteelCommandRuntime, argument,
9 literal,
10 },
11 registration::CommandRegistration,
12};
13use crate::entity::damage::DamageSource;
14use steel_registry::vanilla_damage_types;
15use steel_utils::Identifier;
16use steel_utils::translations::{COMMANDS_DAMAGE_INVULNERABLE, COMMANDS_DAMAGE_SUCCESS};
17use text_components::TextComponent;
18
19pub(super) fn registration() -> CommandRegistration<CommandSource> {
20 CommandRegistration::new(Identifier::vanilla_static("damage"), |_| command())
21}
22
23fn command() -> CommandNodeBuilder<CommandSource, SteelCommandRuntime> {
24 literal("damage").then(
25 argument("target", SteelArgumentType::entity()).then(
26 argument("amount", ArgumentType::float(0.0, f32::MAX))
27 .executes(damage)
28 .then(
29 argument("damageType", SteelArgumentType::damage_type())
30 .executes(damage)
31 .then(literal("at").then(
32 argument("location", SteelArgumentType::vec3(true)).executes(damage),
33 ))
34 .then(
35 literal("by").then(
36 argument("entity", SteelArgumentType::entity())
37 .executes(damage)
38 .then(
39 literal("from").then(
40 argument("cause", SteelArgumentType::entity())
41 .executes(damage),
42 ),
43 ),
44 ),
45 ),
46 ),
47 ),
48 )
49}
50
51fn damage(context: &SteelCommandContext<CommandSource>) -> Result<i32, CommandSyntaxError> {
52 let target = context.entity("target")?;
53 let amount = context.float("amount")?;
54
55 let damage_type = context
57 .damage_type("damageType")
58 .unwrap_or(&vanilla_damage_types::GENERIC);
59
60 let mut damage_source = DamageSource::environment(damage_type);
62
63 if let Ok(coordinates) = context.coordinates("location") {
65 damage_source = damage_source.with_source_position(coordinates.position(context.source()));
66 }
67
68 if let Ok(entity) = context.entity("entity") {
70 damage_source = damage_source
71 .with_direct_entity(Arc::clone(&entity))
72 .with_causing_entity(entity);
73
74 if let Ok(cause) = context.entity("cause") {
76 damage_source = damage_source.with_causing_entity(cause);
77 }
78 }
79
80 let Some(target_world) = target.level() else {
81 return Err(CommandSyntaxError::dynamic(
82 "The entity is not in a world or the world was dropped.",
83 ));
84 };
85
86 if target.hurt(&target_world, &damage_source, amount) {
87 context.source().send_success(
88 &COMMANDS_DAMAGE_SUCCESS
89 .message([
90 TextComponent::plain(format!("{amount:?}")),
91 target.display_name(),
92 ])
93 .component(),
94 true,
95 );
96 Ok(1)
97 } else {
98 context
99 .source()
100 .send_failure(COMMANDS_DAMAGE_INVULNERABLE.msg().component());
101 Ok(0)
102 }
103}