diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-01-24 18:43:16 +0100 |
|---|---|---|
| committer | tpart <tpart120@proton.me> | 2026-02-26 20:48:35 +0100 |
| commit | 6801c48360f4ffa47b174c0607d88d720733080f (patch) | |
| tree | e7d57e8825d623a20fceea8c1aca11848c7c344c /server/data/src/recipes.rs | |
| parent | b634bad931f530ee0a207e1461ffc5e52ebb83e3 (diff) | |
| download | hurrycurry-6801c48360f4ffa47b174c0607d88d720733080f.tar hurrycurry-6801c48360f4ffa47b174c0607d88d720733080f.tar.bz2 hurrycurry-6801c48360f4ffa47b174c0607d88d720733080f.tar.zst | |
modify data code to load tile stack maps
Diffstat (limited to 'server/data/src/recipes.rs')
| -rw-r--r-- | server/data/src/recipes.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/server/data/src/recipes.rs b/server/data/src/recipes.rs new file mode 100644 index 00000000..e4d68a7d --- /dev/null +++ b/server/data/src/recipes.rs @@ -0,0 +1,125 @@ +/* + Hurry Curry! - a game about cooking + Copyright (C) 2026 Hurry Curry! Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +*/ + +use crate::registry::ItemTileRegistry; +use anyhow::{Result, anyhow}; +use hurrycurry_protocol::{Demand, ItemIndex, Recipe}; +use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, BTreeSet}; + +#[rustfmt::skip] +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RecipeDecl { + tile: Option<String>, + #[serde(default)] inputs: Vec<String>, + #[serde(default)] outputs: Vec<String>, + #[serde(default)] action: RecipeDeclAction, + #[serde(default)] warn: bool, + revert_duration: Option<f32>, + duration: Option<f32>, + points: Option<i64>, + group: Option<String>, + #[serde(default)] group_hidden: bool, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)] +#[serde(rename_all = "snake_case")] +pub enum RecipeDeclAction { + #[default] + Never, + Passive, + Active, + Instant, + Demand, +} + +#[allow(clippy::type_complexity)] +pub(crate) fn load_recipes( + recipes_in: Vec<RecipeDecl>, + reg: &ItemTileRegistry, +) -> Result<( + Vec<Recipe>, + Vec<Demand>, + BTreeMap<String, BTreeSet<ItemIndex>>, +)> { + let mut recipes = Vec::new(); + let mut demands = Vec::new(); + let mut recipe_groups = BTreeMap::<String, BTreeSet<ItemIndex>>::new(); + + for mut r in recipes_in { + #[cfg(feature = "fast_recipes")] + match r.action { + RecipeDeclAction::Passive | RecipeDeclAction::Active => { + if !r.warn { + r.duration = Some(0.5) + } + } + _ => (), + } + + let r2 = r.clone(); + let mut inputs = r.inputs.into_iter().map(|i| reg.register_item(i)); + let mut outputs = r.outputs.into_iter().map(|o| reg.register_item(o)); + let tile = r.tile.map(|t| reg.register_tile(t)); + if let Some(g) = r.group + && !r.group_hidden + { + recipe_groups.entry(g).or_default().extend(inputs.clone()); + } + match r.action { + RecipeDeclAction::Never => {} + RecipeDeclAction::Passive => recipes.push(Recipe::Passive { + speed: 1. / r.duration.ok_or(anyhow!("duration for passive missing"))?, + warn: r.warn, + tile, + revert_speed: r.revert_duration.map(|d| 1. / d), + input: inputs + .next() + .ok_or(anyhow!("passive recipe without input"))?, + output: outputs.next(), + }), + RecipeDeclAction::Active => recipes.push(Recipe::Active { + speed: 1. / r.duration.ok_or(anyhow!("duration for active missing"))?, + tile, + input: inputs + .next() + .ok_or(anyhow!("active recipe without input"))?, + outputs: [outputs.next(), outputs.next()], + }), + RecipeDeclAction::Instant => { + recipes.push(Recipe::Instant { + points: r.points.take().unwrap_or(0), + tile, + inputs: [inputs.next(), inputs.next()], + outputs: [outputs.next(), outputs.next()], + }); + } + RecipeDeclAction::Demand => demands.push(Demand { + input: inputs.next().ok_or(anyhow!("demand needs inputs"))?, + output: outputs.next(), + duration: r.duration.unwrap_or(10.), + points: 0, // assigned later when filtering + }), + } + assert_eq!(inputs.next(), None, "{r2:?} inputs left over"); + assert_eq!(outputs.next(), None, "{r2:?} outputs left over"); + assert_eq!(r.points, None, "points specified where not possible") + } + + Ok((recipes, demands, recipe_groups)) +} |