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