aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/data/src/filter_demands.rs8
-rw-r--r--server/data/src/index.rs6
-rw-r--r--server/data/src/lib.rs148
3 files changed, 97 insertions, 65 deletions
diff --git a/server/data/src/filter_demands.rs b/server/data/src/filter_demands.rs
index ab175d98..99246252 100644
--- a/server/data/src/filter_demands.rs
+++ b/server/data/src/filter_demands.rs
@@ -25,6 +25,12 @@ pub fn filter_demands_and_recipes(
demands: &mut Vec<Demand>,
recipes: &mut Vec<Recipe>,
) {
+ debug!(
+ "running demand filter with {} recipes and {} demands",
+ recipes.len(),
+ demands.len()
+ );
+
// Remove tile-bound recipes that cant be performed
recipes.retain(|r| r.tile().map_or(true, |t| map_tiles.contains(&t)));
@@ -89,7 +95,7 @@ pub fn filter_demands_and_recipes(
}
});
debug!(
- "{} recipes and {} demands left",
+ "{} applicable recipes and {} demands selected",
recipes.len(),
demands.len()
)
diff --git a/server/data/src/index.rs b/server/data/src/index.rs
index 9a44d202..a74b283c 100644
--- a/server/data/src/index.rs
+++ b/server/data/src/index.rs
@@ -18,6 +18,7 @@
use anyhow::{Context, Result, anyhow, bail};
use hurrycurry_protocol::{Gamedata, MapMetadata};
+use log::debug;
use serde::Deserialize;
use std::{
collections::{HashMap, HashSet},
@@ -70,6 +71,7 @@ impl DataIndex {
Ok(read_to_string(path)?)
}
pub fn generate(&self, map: &str) -> Result<(Gamedata, Serverdata)> {
+ debug!("Loading map {map}...");
let map_in: MapDecl = serde_yml::from_str(
&self
.read_map(map)
@@ -83,7 +85,9 @@ impl DataIndex {
)
.context("Failed to parse recipe file")?;
- build_data(&self.maps, map.to_string(), map_in, recipes_in)
+ let data = build_data(&self.maps, map.to_string(), map_in, recipes_in)?;
+ debug!("Done.");
+ Ok(data)
}
pub fn generate_with_book(&self, map: &str) -> Result<(Gamedata, Serverdata)> {
let (gd, mut sd) = self.generate(map)?;
diff --git a/server/data/src/lib.rs b/server/data/src/lib.rs
index 86dec209..d316d0b7 100644
--- a/server/data/src/lib.rs
+++ b/server/data/src/lib.rs
@@ -29,6 +29,7 @@ use hurrycurry_protocol::{
book::Book,
glam::{IVec2, Vec2},
};
+use log::debug;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
@@ -132,71 +133,10 @@ fn build_data(
map_in: MapDecl,
recipes_in: Vec<RecipeDecl>,
) -> Result<(Gamedata, Serverdata)> {
+ debug!("Preparing gamedata for {map_name}");
let reg = ItemTileRegistry::default();
- let mut recipes = Vec::new();
- let mut demands = Vec::new();
- let mut entities = 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 {
- if !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")
- }
+ let (mut recipes, mut demands, recipe_groups) = load_recipes(recipes_in, &reg)?;
let mut tile_specs = BTreeMap::new();
for (char, tile_spec_raw) in map_in.tiles {
@@ -205,6 +145,7 @@ fn build_data(
tile_specs.insert(char, TileArgs::try_parse_from(toks)?);
}
+ let mut entities = Vec::new();
let mut chef_spawn = None;
let mut customer_spawn = None;
let mut initial_map = HashMap::new();
@@ -270,6 +211,7 @@ fn build_data(
for e in &entities {
e.run_register(&reg);
}
+ debug!("{} entites created", entities.len());
filter_demands_and_recipes(&tiles_used, &items_used, &mut demands, &mut recipes);
@@ -301,6 +243,11 @@ fn build_data(
let item_names = reg.items.into_inner().unwrap();
let tile_names = reg.tiles.into_inner().unwrap();
+ debug!(
+ "{} items and {} tiles registered",
+ item_names.len(),
+ tile_names.len()
+ );
let default_timer = if map_name.ends_with("lobby") {
None
@@ -341,6 +288,81 @@ fn build_data(
))
}
+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 {
+ if !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))
+}
+
#[derive(Default)]
pub(crate) struct ItemTileRegistry {
tiles: RwLock<Vec<String>>,