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