use "input:____" for searching by recipe input

This commit is contained in:
Isidor Nielsen 2021-10-10 15:44:43 +00:00 committed by Marcel
parent 4be50b8c56
commit f0864a7b0a
2 changed files with 57 additions and 10 deletions

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Shrubs, a system for spawning smaller tree-like plants into the world. - Shrubs, a system for spawning smaller tree-like plants into the world.
- Waterfalls - Waterfalls
- Sailing boat (currently requires spawning in) - Sailing boat (currently requires spawning in)
- Added a filter search function for crafting menu, use "input:_____" to search for recipe inputs
- Added catalan (Catalonia) language translation - Added catalan (Catalonia) language translation
### Changed ### Changed

View File

@ -217,6 +217,21 @@ pub struct State {
selected_recipe: Option<String>, selected_recipe: Option<String>,
} }
enum SearchFilter {
None,
Input,
Nonexistant,
}
impl SearchFilter {
fn parse_from_str(string: &str) -> Self {
match string {
"input" => Self::Input,
_ => Self::Nonexistant,
}
}
}
impl<'a> Widget for Crafting<'a> { impl<'a> Widget for Crafting<'a> {
type Event = Vec<Event>; type Event = Vec<Event>;
type State = State; type State = State;
@ -407,6 +422,29 @@ impl<'a> Widget for Crafting<'a> {
.set(state.ids.category_imgs[i], ui); .set(state.ids.category_imgs[i], ui);
} }
// TODO: Consider UX for filtering searches, maybe a checkbox or a dropdown if
// more filters gets added
let mut _lower_case_search = String::new();
let (search_filter, search_keys) = {
if let Some(key) = &self.show.crafting_search_key {
_lower_case_search = key.as_str().to_lowercase();
_lower_case_search
.split_once(':')
.map(|(filter, key)| {
(
SearchFilter::parse_from_str(filter),
key.split_whitespace().collect(),
)
})
.unwrap_or((
SearchFilter::None,
_lower_case_search.split_whitespace().collect(),
))
} else {
(SearchFilter::None, vec![])
}
};
// First available recipes, then ones with available materials, // First available recipes, then ones with available materials,
// then unavailable ones, each sorted by quality and then alphabetically // then unavailable ones, each sorted by quality and then alphabetically
// In the tuple, "name" is the recipe book key, and "recipe.output.0.name()" // In the tuple, "name" is the recipe book key, and "recipe.output.0.name()"
@ -415,16 +453,24 @@ impl<'a> Widget for Crafting<'a> {
.client .client
.recipe_book() .recipe_book()
.iter() .iter()
.filter(|(_, recipe)| { .filter(|(_, recipe)| match search_filter {
SearchFilter::None => {
let output_name = recipe.output.0.name.to_lowercase(); let output_name = recipe.output.0.name.to_lowercase();
if let Some(key) = &self.show.crafting_search_key { search_keys
key.as_str() .iter()
.to_lowercase() .all(|&substring| output_name.contains(substring))
.split_whitespace() },
.all(|substring| output_name.contains(substring)) SearchFilter::Input => recipe.inputs().any(|(input, _)| {
} else { let input_name = match input {
true RecipeInput::Item(def) => def.name.as_str(),
RecipeInput::Tag(tag) => tag.name(),
} }
.to_lowercase();
search_keys
.iter()
.all(|&substring| input_name.contains(substring))
}),
_ => false,
}) })
.map(|(name, recipe)| { .map(|(name, recipe)| {
let has_materials = self.client.available_recipes().get(name.as_str()).is_some(); let has_materials = self.client.available_recipes().get(name.as_str()).is_some();