aboutsummaryrefslogtreecommitdiff
path: root/server/src/data/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/data/mod.rs')
-rw-r--r--server/src/data/mod.rs89
1 files changed, 51 insertions, 38 deletions
diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs
index 17ebd5bf..1fab912a 100644
--- a/server/src/data/mod.rs
+++ b/server/src/data/mod.rs
@@ -19,6 +19,7 @@ pub mod demands;
use crate::entity::{construct_entity, Entities, EntityDecl};
use anyhow::{anyhow, bail, Context, Result};
+use clap::Parser;
use demands::generate_demands;
use hurrycurry_bot::algos::ALGO_CONSTRUCTORS;
use hurrycurry_protocol::{
@@ -28,7 +29,7 @@ use hurrycurry_protocol::{
};
use serde::{Deserialize, Serialize};
use std::{
- collections::{BTreeMap, HashMap, HashSet},
+ collections::{BTreeMap, BTreeSet, HashMap, HashSet},
fs::{read_to_string, File},
path::PathBuf,
str::FromStr,
@@ -63,22 +64,35 @@ pub struct RecipeDecl {
#[rustfmt::skip]
#[derive(Debug, Clone, Deserialize)]
pub struct MapDecl {
- #[serde(default)] recipes: Option<String>,
map: Vec<String>,
tiles: HashMap<char, String>,
- #[serde(default)] items: HashMap<char, String>,
- collider: Vec<String>,
- walkable: Vec<String>,
- chef_spawn: char,
- customer_spawn: char,
+ #[serde(default)] recipes: Option<String>,
#[serde(default)] hand_count: Option<usize>,
#[serde(default)] entities: Vec<EntityDecl>,
- #[serde(default)] tile_entities: HashMap<char, EntityDecl>,
#[serde(default)] score_baseline: i64,
#[serde(default)] default_timer: Option<u64>,
#[serde(default)] flags: ServerdataFlags,
}
+#[derive(Parser)]
+struct TileArgs {
+ tile_name: String,
+ #[clap(short = 'c', long)]
+ collider: bool,
+ #[clap(short = 'x', long)]
+ exclusive: bool,
+ #[clap(short = 'w', long)]
+ walkable: bool,
+ #[clap(long)]
+ book: bool,
+ #[clap(long)]
+ chef_spawn: bool,
+ #[clap(long)]
+ customer_spawn: bool,
+ #[clap(short = 'i', long)]
+ item: Option<String>,
+}
+
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DemandDecl {
from: String,
@@ -92,7 +106,7 @@ pub struct DemandDecl {
pub struct Serverdata {
pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>,
pub chef_spawn: Vec2,
- pub customer_spawn: Vec2,
+ pub customer_spawn: Option<Vec2>,
pub score_baseline: i64,
pub default_timer: Option<Duration>,
pub book: Book,
@@ -240,48 +254,53 @@ pub fn build_data(
assert_eq!(r.points, None, "points specified where not possible")
}
- let mut chef_spawn = Vec2::new(0., 0.);
- let mut customer_spawn = Vec2::new(0., 0.);
+ let mut chef_spawn = None;
+ let mut customer_spawn = None;
let mut initial_map = HashMap::new();
let mut tiles_used = HashSet::new();
let mut items_used = HashSet::new();
+ let mut tile_walkable = HashSet::new();
+ let mut exclusive_tiles = BTreeSet::new();
for (y, line) in map_in.map.iter().enumerate() {
for (x, tile) in line.chars().enumerate() {
if tile == ' ' {
continue; // space is empty space
}
let pos = IVec2::new(x as i32, y as i32);
- if tile == map_in.chef_spawn {
- chef_spawn = pos.as_vec2() + Vec2::splat(0.5);
- }
- if tile == map_in.customer_spawn {
- customer_spawn = pos.as_vec2() + Vec2::splat(0.5);
- }
- let tilename = map_in
+
+ let tile_spec = map_in
.tiles
.get(&tile)
.ok_or(anyhow!("tile {tile} is undefined"))?
.clone();
+ let mut toks = shlex::split(&tile_spec).ok_or(anyhow!("tile spec quoting invalid"))?;
+ toks.insert(0, "tile-spec".to_string()); // exe name
+ let tile_spec = TileArgs::try_parse_from(toks)?;
- let itemname = map_in.items.get(&tile).cloned();
- let tile = reg.register_tile(tilename);
- let item = itemname.map(|i| reg.register_item(i));
+ let tile = reg.register_tile(tile_spec.tile_name);
tiles_used.insert(tile);
- if let Some(i) = item {
- items_used.insert(i);
- };
+ let item = tile_spec.item.map(|i| reg.register_item(i));
+ items_used.extend(item);
initial_map.insert(pos, (tile, item));
- }
- }
- for (y, line) in map_in.map.iter().enumerate() {
- for (x, tile) in line.trim().chars().enumerate() {
- let pos = IVec2::new(x as i32, y as i32);
- if let Some(ent) = map_in.tile_entities.get(&tile) {
- entities.push(construct_entity(Some(pos), ent, &reg)?);
+ if tile_spec.chef_spawn {
+ chef_spawn = Some(pos.as_vec2() + Vec2::splat(0.5));
+ }
+ if tile_spec.customer_spawn {
+ customer_spawn = Some(pos.as_vec2() + Vec2::splat(0.5));
+ }
+ if tile_spec.book {
+ entities.push(construct_entity(Some(pos), &EntityDecl::Book, &reg)?);
+ }
+ if tile_spec.walkable {
+ tile_walkable.insert(tile);
+ }
+ if tile_spec.walkable || tile_spec.collider || tile_spec.exclusive {
+ exclusive_tiles.insert(tile);
}
}
}
+ let chef_spawn = chef_spawn.ok_or(anyhow!("map has no chef spawn"))?;
entities.extend(
map_in
@@ -308,8 +327,7 @@ pub fn build_data(
let mut tile_placeable_items = BTreeMap::new();
let mut tile_interactable_empty = HashSet::new();
- for tile_name in map_in.collider.iter().chain(map_in.walkable.iter()) {
- let tile = reg.register_tile(tile_name.to_string());
+ for tile in exclusive_tiles {
let whitelist = recipes
.iter()
.filter(|r| r.tile() == Some(tile))
@@ -323,11 +341,6 @@ pub fn build_data(
tile_interactable_empty.insert(tile);
}
}
- let tile_walkable = map_in
- .walkable
- .into_iter()
- .map(|name| reg.register_tile(name))
- .collect();
let item_names = reg.items.into_inner().unwrap();
let tile_names = reg.tiles.into_inner().unwrap();