steel_core/command/execution/
world.rs1use std::{fmt, sync::Arc};
4
5use steel_utils::{Identifier, translations};
6
7use super::{CommandArgumentSource, CommandSource, argument::parse_identifier};
8use crate::{
9 command::brigadier::{CommandSyntaxError, StringReader, SuggestionsBuilder},
10 world::World,
11};
12
13#[derive(Clone, Debug, PartialEq, Eq)]
15pub(crate) enum WorldArgument {
16 Key(Identifier),
17 Relative(Box<str>),
18}
19
20impl WorldArgument {
21 pub(crate) fn resolve(&self, source: &CommandSource) -> Result<Arc<World>, CommandSyntaxError> {
22 let world = match self {
23 Self::Key(key) => source.server().worlds.get(key),
24 Self::Relative(path) => {
25 let key = Identifier::new(source.world().domain().to_owned(), path.to_string());
26 source.server().worlds.get(&key)
27 }
28 };
29 world.map_or_else(
30 || {
31 let message = translations::ARGUMENT_DIMENSION_INVALID
32 .message([self.to_string()])
33 .component();
34 Err(CommandSyntaxError::dynamic(message))
35 },
36 |world| Ok(Arc::clone(world)),
37 )
38 }
39}
40
41impl fmt::Display for WorldArgument {
42 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 Self::Key(key) => write!(formatter, "{key}"),
45 Self::Relative(path) => formatter.write_str(path),
46 }
47 }
48}
49
50pub(super) fn parse_world_argument(
51 reader: &mut StringReader<'_>,
52) -> Result<WorldArgument, CommandSyntaxError> {
53 let start_byte = reader.read_so_far().len();
54 let key = parse_identifier(reader)?;
55 let raw = &reader.read_so_far()[start_byte..];
56 if raw.contains(':') {
57 Ok(WorldArgument::Key(key))
58 } else {
59 Ok(WorldArgument::Relative(key.path.to_string().into()))
60 }
61}
62
63pub(super) fn suggest_worlds<S>(builder: &mut SuggestionsBuilder<'_>, source: &S)
64where
65 S: CommandArgumentSource + ?Sized,
66{
67 let prefix = builder.remaining_lowercase().to_owned();
68 for world in source
69 .command_world_names()
70 .into_iter()
71 .filter(|world| world.starts_with(&prefix))
72 {
73 builder.suggest(world);
74 }
75}