steel_core/command/execution/
biome.rs1use steel_registry::{
4 BIOMES_REGISTRY, REGISTRY, RegistryExt as _, TaggedRegistryExt as _, biome::BiomeRef,
5};
6use steel_utils::{Identifier, translations};
7
8use super::argument::{identifier_matches, parse_identifier, unknown_resource};
9use crate::command::brigadier::{
10 CommandSyntaxError, CommandSyntaxErrorKind, StringReader, SuggestionsBuilder,
11};
12
13#[derive(Clone, Debug, PartialEq)]
15pub(crate) enum BiomeOrTag {
16 Biome(BiomeRef),
17 Tag(Identifier),
18}
19
20impl BiomeOrTag {
21 pub(crate) fn matches(&self, biome: BiomeRef) -> bool {
22 match self {
23 Self::Biome(expected) => *expected == biome,
24 Self::Tag(tag) => biome.has_tag(tag),
25 }
26 }
27}
28
29pub(super) fn parse_biome_or_tag(
30 reader: &mut StringReader<'_>,
31) -> Result<BiomeOrTag, CommandSyntaxError> {
32 if reader.peek() != Some('#') {
33 let key = parse_identifier(reader)?;
34 return REGISTRY.biomes.by_key(&key).map_or_else(
35 || Err(unknown_resource(reader, &key, &BIOMES_REGISTRY)),
36 |biome| Ok(BiomeOrTag::Biome(biome)),
37 );
38 }
39
40 let start = reader.checkpoint();
41 reader.skip();
42 let key = match parse_identifier(reader) {
43 Ok(key) => key,
44 Err(error) => {
45 reader.restore(start);
46 return Err(error);
47 }
48 };
49 if REGISTRY.biomes.tag_keys().any(|tag| tag == &key) {
50 return Ok(BiomeOrTag::Tag(key));
51 }
52
53 let message = translations::ARGUMENT_RESOURCE_TAG_NOT_FOUND
54 .message([key.to_string(), BIOMES_REGISTRY.to_string()])
55 .component();
56 let error = reader.error(CommandSyntaxErrorKind::Dynamic(Box::new(message)));
57 reader.restore(start);
58 Err(error)
59}
60
61pub(super) fn suggest_biomes(builder: &mut SuggestionsBuilder<'_>) {
62 let remaining = builder.remaining_lowercase();
63 let suggestions = if let Some(tag_prefix) = remaining.strip_prefix('#') {
64 REGISTRY
65 .biomes
66 .tag_keys()
67 .filter(|tag| identifier_matches(tag_prefix, tag))
68 .map(|tag| format!("#{tag}"))
69 .collect::<Vec<_>>()
70 } else {
71 REGISTRY
72 .biomes
73 .iter()
74 .filter(|(_, biome)| identifier_matches(remaining, &biome.key))
75 .map(|(_, biome)| biome.key.to_string())
76 .chain(
77 REGISTRY
78 .biomes
79 .tag_keys()
80 .filter(|tag| identifier_matches(remaining, tag))
81 .map(|tag| format!("#{tag}")),
82 )
83 .collect()
84 };
85 for suggestion in suggestions {
86 builder.suggest(suggestion);
87 }
88}