aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-09-01 20:09:06 +0200
committermetamuffin <metamuffin@disroot.org>2024-09-01 20:09:06 +0200
commiteb7fa5392997ac5c165d1ae011e57a1b7fcac084 (patch)
treededaf078a8817a976ead6568dbf93bf79f3f395b
parent4ad82d4944bc8ea00fcfe324c8004b079ec48c18 (diff)
downloadhurrycurry-eb7fa5392997ac5c165d1ae011e57a1b7fcac084.tar
hurrycurry-eb7fa5392997ac5c165d1ae011e57a1b7fcac084.tar.bz2
hurrycurry-eb7fa5392997ac5c165d1ae011e57a1b7fcac084.tar.zst
server support for nested map directory
-rw-r--r--data/index.yaml2
-rw-r--r--data/makefile2
-rw-r--r--data/maps/campaign/01.yaml70
-rw-r--r--data/maps/campaign/lobby.yaml59
-rw-r--r--server/src/bin/graph.rs9
-rw-r--r--server/src/bin/graph_summary.rs8
-rw-r--r--server/src/data/mod.rs38
-rw-r--r--server/src/server.rs2
-rw-r--r--server/src/state.rs18
9 files changed, 160 insertions, 48 deletions
diff --git a/data/index.yaml b/data/index.yaml
index 2073fd5d..199ed423 100644
--- a/data/index.yaml
+++ b/data/index.yaml
@@ -29,7 +29,6 @@ demands:
# 5 Unplayable
maps:
- lobby: { name: "Lobby", players: 0, difficulty: 1 }
sophomore: { name: "Sophomore", players: 1, difficulty: 1 }
junior: { name: "Junior", players: 3, difficulty: 1 }
senior: { name: "Senior", players: 4, difficulty: 1 }
@@ -51,7 +50,6 @@ maps:
5star: { name: "5 Star", players: 4, difficulty: 3 }
auto_sushi: { name: "AutoSushi", players: 2, difficulty: 2 }
factory: { name: "Factory", players: 3, difficulty: 4 }
- debug: { name: "DEBUG", players: 0, difficulty: 5 }
recipes:
- none
diff --git a/data/makefile b/data/makefile
index 95dc953a..23956869 100644
--- a/data/makefile
+++ b/data/makefile
@@ -14,7 +14,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
all: $(patsubst %.ts,%.yaml,$(wildcard recipes/*.ts))
-graphs: $(patsubst %.ts,%.svg,$(wildcard recipes/*.ts))
+graphs: recipes/default.svg
recipes/%.yaml: recipes/%.ts
DENO_NO_UPDATE_CHECK=1 deno run $< > $@
diff --git a/data/maps/campaign/01.yaml b/data/maps/campaign/01.yaml
new file mode 100644
index 00000000..8fe64c5b
--- /dev/null
+++ b/data/maps/campaign/01.yaml
@@ -0,0 +1,70 @@
+# Hurry Curry! - a game about cooking
+# Copyright 2024 metamuffin
+#
+# 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/>.
+#
+score_baseline: 100
+map:
+ - "*''''*'''*'''''*'''"
+ - "'''*''''*'*'*'''*'*"
+ - "''████▒█████▒███'*"
+ - "*'█tc....█..~.s█''"
+ - "''▒c.ctc.d....⌷█'*"
+ - "'*█tc.c..█....C█'*"
+ - "''█c.....█XTppp█''"
+ - "*'████dd████████''"
+ - "'*''''__'''''''''''"
+ - "'''*''____________!"
+ - "'*'''''''''''''''''"
+
+tiles:
+ "⌷": counter
+ "p": counter
+ "t": table
+ "w": counter-window
+ "s": sink
+ "C": cuttingboard
+ "T": tomato-crate
+ "X": trash
+
+ "c": chair
+ "~": floor
+ ".": floor
+ "'": grass
+ "*": tree
+ "!": path
+ "_": path
+ "d": door
+ "▒": wall-window
+ "█": wall
+
+items:
+ "p": plate
+
+entities:
+ - !customers
+
+chef_spawn: "~"
+customer_spawn: "!"
+
+walkable:
+ - door
+ - floor
+ - chair
+ - grass
+ - path
+
+collider:
+ - wall
+ - wall-window
+ - tree
diff --git a/data/maps/campaign/lobby.yaml b/data/maps/campaign/lobby.yaml
new file mode 100644
index 00000000..6090d96a
--- /dev/null
+++ b/data/maps/campaign/lobby.yaml
@@ -0,0 +1,59 @@
+# Hurry Curry! - a game about cooking
+# Copyright 2024 metamuffin
+#
+# 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/>.
+#
+score_baseline: 0
+map:
+ - "'*''''''''''''*'"
+ - "*'''''*'''*'''''"
+ - "'*''*''''*'*'*'*"
+ - "*''''''''''''*''"
+ - "*''''''''''''**'"
+ - "''''''''''''''''"
+ - "''*''''''''''*'*"
+ - "'*'''''~''''''''"
+ - "''''''''''''''*'"
+ - "'*'''''''''''*''"
+ - "''*'''''''''''*'"
+ - "'''''''''''''*''"
+ - "'*'''''''''''*''"
+ - "''*'''*'''*''*''"
+ - "'*''*''**'''**''"
+ - "*'''''''''*''''*"
+
+tiles:
+ "t": table
+ "T": table
+ "s": sink
+ "c": chair
+ "~": floor
+ ".": floor
+ "b": book
+ "'": grass
+ "*": tree
+ "█": wall
+
+items:
+ "t": tomato-soup-plate
+ "T": bread-slice-plate
+
+chef_spawn: "~"
+customer_spawn: "!"
+
+walkable:
+ - floor
+ - chair
+ - grass
+collider:
+ - wall
diff --git a/server/src/bin/graph.rs b/server/src/bin/graph.rs
index 7019de9c..0bc3702f 100644
--- a/server/src/bin/graph.rs
+++ b/server/src/bin/graph.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use anyhow::{anyhow, Result};
+use anyhow::Result;
use hurrycurry_protocol::{Demand, ItemIndex, Recipe, RecipeIndex};
use hurrycurry_server::data::DataIndex;
@@ -26,12 +26,7 @@ async fn main() -> Result<()> {
println!("digraph {{");
- let rn = std::env::args()
- .nth(1)
- .ok_or(anyhow!("first arg should be recipe set name"))?;
-
- let (data, _, _) = index.generate(format!("5star-{rn}")).await?;
-
+ let (data, _, _) = index.generate("5star").await?;
for i in 0..data.item_names.len() {
println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
}
diff --git a/server/src/bin/graph_summary.rs b/server/src/bin/graph_summary.rs
index 12df0b1a..2c97799a 100644
--- a/server/src/bin/graph_summary.rs
+++ b/server/src/bin/graph_summary.rs
@@ -15,7 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use anyhow::{anyhow, Result};
+use anyhow::Result;
use hurrycurry_protocol::{ItemIndex, Recipe, TileIndex};
use hurrycurry_server::data::DataIndex;
use std::collections::HashSet;
@@ -27,11 +27,7 @@ async fn main() -> Result<()> {
println!("digraph {{");
- let rn = std::env::args()
- .nth(1)
- .ok_or(anyhow!("first arg should be recipe set name"))?;
-
- let (data, sdata, _) = index.generate(format!("5star-{rn}")).await?;
+ let (data, sdata, _) = index.generate("5star").await?;
struct Node {
inputs: Vec<ItemIndex>,
diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs
index dd916a93..7ec0707d 100644
--- a/server/src/data/mod.rs
+++ b/server/src/data/mod.rs
@@ -69,6 +69,8 @@ pub struct RecipeDecl {
#[derive(Debug, Clone, Deserialize)]
pub struct MapDecl {
+ #[serde(default)]
+ recipes: Option<String>,
map: Vec<String>,
tiles: HashMap<char, String>,
#[serde(default)]
@@ -96,7 +98,6 @@ pub struct DemandDecl {
#[derive(Debug,Clone, Default)]
#[rustfmt::skip]
pub struct Serverdata {
- pub spec: String,
pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>,
pub chef_spawn: Vec2,
pub customer_spawn: Vec2,
@@ -125,8 +126,9 @@ impl DataIndex {
}
pub async fn read_map(&self, name: &str) -> Result<String> {
- if !self.maps.contains_key(name) {
- bail!("unknown map: {name:?}");
+ // Scary!
+ if name.contains("..") || name.starts_with("/") || name.contains("//") {
+ bail!("illegal map path");
}
let path = data_dir().join(format!("maps/{name}.yaml"));
Ok(read_to_string(path).await?)
@@ -138,26 +140,25 @@ impl DataIndex {
let path = data_dir().join(format!("recipes/{name}.yaml"));
Ok(read_to_string(path).await?)
}
-
- pub async fn generate(&self, spec: String) -> Result<(Gamedata, Serverdata, Entities)> {
- let (map, recipes) = spec.split_once("-").unwrap_or((spec.as_str(), "default"));
-
- let map_in = serde_yml::from_str(&self.read_map(map).await?)?;
- let recipes_in = serde_yml::from_str(&self.read_recipes(recipes).await?)?;
-
- Ok(build_data(
- &self.maps,
- spec.clone(),
- map.to_string(),
- map_in,
- recipes_in,
- )?)
+ pub async fn generate(&self, map: &str) -> Result<(Gamedata, Serverdata, Entities)> {
+ let map_in: MapDecl = serde_yml::from_str(&self.read_map(map).await?)?;
+ let recipes_in = serde_yml::from_str(
+ &self
+ .read_recipes(
+ map_in
+ .recipes
+ .as_ref()
+ .map(|a| a.as_str())
+ .unwrap_or("default"),
+ )
+ .await?,
+ )?;
+ Ok(build_data(&self.maps, map.to_string(), map_in, recipes_in)?)
}
}
pub fn build_data(
maps: &HashMap<String, MapMetadata>,
- spec: String,
map_name: String,
map_in: MapDecl,
recipes_in: Vec<RecipeDecl>,
@@ -301,7 +302,6 @@ pub fn build_data(
tile_names,
},
Serverdata {
- spec,
initial_map,
chef_spawn,
customer_spawn,
diff --git a/server/src/server.rs b/server/src/server.rs
index 75ecede1..cce99266 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -252,7 +252,6 @@ impl Server<'_> {
packet_out: &mut VecDeque<PacketC>,
) {
self.game.load(gamedata, &serverdata, timer, packet_out);
- self.state.data = serverdata.into();
for mut e in self.state.entities.drain(..) {
e.destructor(EntityContext {
game: self.game,
@@ -262,6 +261,7 @@ impl Server<'_> {
dt: 0.,
});
}
+ self.state.data = serverdata.into();
self.state.entities = entities;
}
diff --git a/server/src/state.rs b/server/src/state.rs
index 20a57b9d..4be0fb5a 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -99,11 +99,7 @@ impl State {
game: &mut game,
state: &mut server,
}
- .load(
- index.generate("lobby-none".to_string()).await?,
- None,
- &mut packet_out,
- );
+ .load(index.generate("lobby").await?, None, &mut packet_out);
}
Ok(Self {
@@ -123,7 +119,7 @@ impl State {
};
if server.tick(dt, &mut self.packet_out) {
server.load(
- self.index.generate("lobby-none".to_string()).await?,
+ self.index.generate("lobby").await?,
None,
&mut self.packet_out,
);
@@ -192,7 +188,7 @@ impl State {
})
.ok();
server.load(
- self.index.generate("lobby-none".to_string()).await?,
+ self.index.generate("lobby").await?,
None,
&mut self.packet_out,
);
@@ -231,7 +227,7 @@ impl State {
};
match command {
Command::Start { spec, timer } => {
- let data = self.index.generate(spec).await?;
+ let data = self.index.generate(&spec).await?;
server.load(data, Some(Duration::from_secs(timer)), &mut self.packet_out);
}
Command::End => {
@@ -249,7 +245,7 @@ impl State {
})
.ok();
server.load(
- self.index.generate("lobby-none".to_string()).await?,
+ self.index.generate("lobby").await?,
None,
&mut self.packet_out,
);
@@ -259,9 +255,7 @@ impl State {
bail!("must be at most one player to reload");
}
server.load(
- self.index
- .generate(server.state.data.spec.to_string())
- .await?,
+ self.index.generate(&server.game.data.current_map).await?,
None,
&mut self.packet_out,
);