steel_core/command/builtins/
defaultgamemode.rs1use steel_utils::{Identifier, translations};
4use text_components::TextComponent;
5
6use super::super::{
7 brigadier::{CommandNodeBuilder, CommandSyntaxError},
8 execution::{
9 CommandSource, SteelArgumentType, SteelCommandContext, SteelCommandRuntime, argument,
10 literal,
11 },
12 registration::CommandRegistration,
13};
14use super::gamemode::game_mode_translation;
15
16pub(super) fn registration() -> CommandRegistration<CommandSource> {
17 CommandRegistration::new(Identifier::vanilla_static("defaultgamemode"), |_| command())
18}
19
20fn command() -> CommandNodeBuilder<CommandSource, SteelCommandRuntime> {
21 literal("defaultgamemode").then(
22 argument("gamemode", SteelArgumentType::game_mode())
23 .executes(set_default_game_mode)
24 .then(
25 argument("domain", SteelArgumentType::domain())
26 .executes(set_default_game_mode_domain),
27 ),
28 )
29}
30
31fn set_default_game_mode(
32 context: &SteelCommandContext<CommandSource>,
33) -> Result<i32, CommandSyntaxError> {
34 let domain = context.source().world().domain().to_owned();
35 apply_default_game_mode(context, &domain)
36}
37
38fn set_default_game_mode_domain(
39 context: &SteelCommandContext<CommandSource>,
40) -> Result<i32, CommandSyntaxError> {
41 let domain = context.domain("domain")?;
42 apply_default_game_mode(context, domain)
43}
44
45fn apply_default_game_mode(
46 context: &SteelCommandContext<CommandSource>,
47 domain: &str,
48) -> Result<i32, CommandSyntaxError> {
49 if !context.source().allows_execution_domain(domain) {
50 return Err(CommandSyntaxError::dynamic(
51 "Players cannot execute commands across Steel domains",
52 ));
53 }
54
55 let game_mode = context.game_mode("gamemode")?;
56 let worlds = context.source().server().worlds.worlds_in_domain(domain);
57
58 for world in worlds {
59 world.set_default_gamemode(game_mode);
60 }
61
62 let message = translations::COMMANDS_DEFAULTGAMEMODE_SUCCESS
67 .message([TextComponent::from(game_mode_translation(game_mode))])
68 .component();
69 context.source().send_success(&message, true);
70 Ok(0)
71}
72
73#[cfg(test)]
74mod tests {
75 use steel_registry::init_vanilla_registry;
76
77 use super::super::create_dispatcher;
78 use crate::command::execution::SteelArgumentType;
79
80 #[test]
81 fn defaultgamemode_graph_matches_shape() {
82 init_vanilla_registry();
83 let Ok(dispatcher) = create_dispatcher() else {
84 panic!("built-in commands should register");
85 };
86 let Some(root) = dispatcher.children(dispatcher.root()).and_then(|children| {
87 children.iter().copied().find(|child| {
88 dispatcher
89 .node(*child)
90 .is_some_and(|node| node.name() == "defaultgamemode")
91 })
92 }) else {
93 panic!("defaultgamemode root should exist");
94 };
95 let Some(game_mode) = dispatcher
96 .children(root)
97 .and_then(|children| children.first())
98 .copied()
99 else {
100 panic!("gamemode argument should exist");
101 };
102 assert!(matches!(
103 dispatcher.node(game_mode),
104 Some(node)
105 if node.is_executable()
106 && node.argument_type() == Some(&SteelArgumentType::game_mode())
107 ));
108 let Some(domain) = dispatcher
109 .children(game_mode)
110 .and_then(|children| children.first())
111 .copied()
112 else {
113 panic!("domain argument should exist");
114 };
115 assert!(matches!(
116 dispatcher.node(domain),
117 Some(node)
118 if node.is_executable()
119 && node.argument_type() == Some(&SteelArgumentType::domain())
120 ));
121 }
122}