summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-07 23:03:07 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-07 23:03:07 +0200
commitcd6e8f3886d764847f92ad75d397e2f2f6ad930a (patch)
treec99e141bc51c2004cdde1b0660ed10b2696f04d8
parentfd46def1ebc10d1f2ee4f4447f33e2dfb35986d2 (diff)
downloadhurrycurry-cd6e8f3886d764847f92ad75d397e2f2f6ad930a.tar
hurrycurry-cd6e8f3886d764847f92ad75d397e2f2f6ad930a.tar.bz2
hurrycurry-cd6e8f3886d764847f92ad75d397e2f2f6ad930a.tar.zst
add option to download map source
-rw-r--r--Cargo.lock7
-rw-r--r--data/index.yaml2
-rw-r--r--server/Cargo.toml1
-rw-r--r--server/src/bin/graph.rs3
-rw-r--r--server/src/data.rs48
-rw-r--r--server/src/main.rs2
-rw-r--r--server/src/state.rs40
7 files changed, 70 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 256e5864..24bc2a0c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -519,6 +519,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+name = "pollster"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
+
+[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -868,6 +874,7 @@ dependencies = [
"futures-util",
"glam",
"log",
+ "pollster",
"rand 0.9.0-alpha.1",
"serde",
"serde_json",
diff --git a/data/index.yaml b/data/index.yaml
index 37229844..6f07e834 100644
--- a/data/index.yaml
+++ b/data/index.yaml
@@ -1,5 +1,3 @@
-initial: [null, lobby, null]
-
demands:
- none
- default
diff --git a/server/Cargo.toml b/server/Cargo.toml
index f09bdf4e..e477bd0f 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -19,3 +19,4 @@ rand = "0.9.0-alpha.1"
shlex = "1.3.0"
clap = { version = "4.5.7", features = ["derive"] }
fake = "2.9.2"
+pollster = "0.3.0"
diff --git a/server/src/bin/graph.rs b/server/src/bin/graph.rs
index 024512c6..766fa851 100644
--- a/server/src/bin/graph.rs
+++ b/server/src/bin/graph.rs
@@ -16,6 +16,7 @@
*/
use anyhow::{anyhow, Result};
+use pollster::FutureExt;
use undercooked::{
data::{DataIndex, Demand},
interaction::Recipe,
@@ -32,7 +33,7 @@ fn main() -> Result<()> {
.nth(1)
.ok_or(anyhow!("first arg should be recipe set name"))?;
- let data = index.generate(format!("small-default-{rn}"))?;
+ let data = index.generate(format!("small-default-{rn}")).block_on()?;
for i in 0..data.item_names.len() {
println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
diff --git a/server/src/data.rs b/server/src/data.rs
index c667e760..258057c0 100644
--- a/server/src/data.rs
+++ b/server/src/data.rs
@@ -20,7 +20,7 @@ use crate::{
interaction::Recipe,
protocol::{DemandIndex, ItemIndex, RecipeIndex, TileIndex},
};
-use anyhow::{anyhow, bail, Context, Result};
+use anyhow::{anyhow, bail, Result};
use glam::{IVec2, Vec2};
use serde::{Deserialize, Serialize};
use std::{
@@ -30,6 +30,7 @@ use std::{
str::FromStr,
sync::{Mutex, RwLock},
};
+use tokio::fs::read_to_string;
#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)]
#[serde(rename_all = "snake_case")]
@@ -126,35 +127,40 @@ fn data_dir() -> PathBuf {
}
impl DataIndex {
- pub fn reload(&mut self) -> anyhow::Result<()> {
+ pub fn reload(&mut self) -> Result<()> {
*self = serde_yaml::from_reader(File::open(data_dir().join("index.yaml"))?)?;
Ok(())
}
- pub fn generate(&self, spec: String) -> anyhow::Result<Gamedata> {
- let (map, rest) = spec.split_once("-").unwrap_or((spec.as_str(), "default"));
- let (demands, recipes) = rest.split_once("-").unwrap_or((rest, "default"));
-
- if !self.maps.contains(map) {
- bail!("unknown map: {map:?}");
+ pub async fn read_map(&self, name: &str) -> Result<String> {
+ if !self.maps.contains(name) {
+ bail!("unknown map: {name:?}");
}
- if !self.demands.contains(demands) {
- bail!("unknown demands: {demands:?}");
+ let path = data_dir().join(format!("maps/{name}.yaml"));
+ Ok(read_to_string(path).await?)
+ }
+ pub async fn read_demands(&self, name: &str) -> Result<String> {
+ if !self.demands.contains(name) {
+ bail!("unknown demands: {name:?}");
}
- if !self.recipes.contains(recipes) {
- bail!("unknown recipes: {recipes:?}");
+ let path = data_dir().join(format!("demands/{name}.yaml"));
+ Ok(read_to_string(path).await?)
+ }
+ pub async fn read_recipes(&self, name: &str) -> Result<String> {
+ if !self.recipes.contains(name) {
+ bail!("unknown recipes: {name:?}");
}
+ let path = data_dir().join(format!("recipes/{name}.yaml"));
+ Ok(read_to_string(path).await?)
+ }
- let map_path = data_dir().join(format!("maps/{map}.yaml"));
- let demands_path = data_dir().join(format!("demands/{demands}.yaml"));
- let recipes_path = data_dir().join(format!("recipes/{recipes}.yaml"));
+ pub async fn generate(&self, spec: String) -> Result<Gamedata> {
+ let (map, rest) = spec.split_once("-").unwrap_or((spec.as_str(), "default"));
+ let (demands, recipes) = rest.split_once("-").unwrap_or((rest, "default"));
- let map_in = serde_yaml::from_reader(File::open(map_path).context("opening map failed")?)?;
- let demands_in =
- serde_yaml::from_reader(File::open(demands_path).context("opening demands failed")?)?;
- let recipes_in = serde_yaml::from_reader(
- File::open(recipes_path).context("opening recipes failed. are they generated yet?")?,
- )?;
+ let map_in = serde_yaml::from_str(&self.read_map(map).await?)?;
+ let demands_in = serde_yaml::from_str(&self.read_demands(demands).await?)?;
+ let recipes_in = serde_yaml::from_str(&self.read_recipes(recipes).await?)?;
let mut gd = Gamedata::build(map_in, demands_in, recipes_in)?;
gd.map_names = self.maps.clone();
diff --git a/server/src/main.rs b/server/src/main.rs
index a144c704..d17dedf8 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -82,7 +82,7 @@ async fn run() -> anyhow::Result<()> {
let (tx, rx) = broadcast::channel::<PacketC>(1024);
- let state = Arc::new(RwLock::new(State::new(tx)?));
+ let state = Arc::new(RwLock::new(State::new(tx).await?));
{
let state = state.clone();
spawn(async move {
diff --git a/server/src/state.rs b/server/src/state.rs
index cd763b18..8f33b6d4 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -6,7 +6,7 @@ use crate::{
protocol::{Message, PacketC, PacketS, PlayerID},
};
use anyhow::{anyhow, bail, Result};
-use clap::Parser;
+use clap::{Parser, ValueEnum};
use log::debug;
use tokio::sync::broadcast::Sender;
@@ -25,6 +25,11 @@ enum Command {
#[arg(default_value = "420")]
timer: u64,
},
+ Download {
+ #[arg(value_enum)]
+ r#type: DownloadType,
+ name: String,
+ },
List,
Effect {
name: String,
@@ -33,13 +38,20 @@ enum Command {
End,
}
+#[derive(ValueEnum, Clone)]
+enum DownloadType {
+ Map,
+ Recipes,
+ Demand,
+}
+
impl State {
- pub fn new(tx: Sender<PacketC>) -> Result<Self> {
+ pub async fn new(tx: Sender<PacketC>) -> Result<Self> {
let mut index = DataIndex::default();
index.reload()?;
let mut game = Game::new();
- game.load(index.generate("lobby-none-none".to_string())?, None);
+ game.load(index.generate("lobby-none-none".to_string()).await?, None);
Ok(Self { game, index, tx })
}
@@ -51,8 +63,10 @@ impl State {
text: format!("Game finished. You reached {} points.", self.game.points),
})
.ok();
- self.game
- .load(self.index.generate("lobby-none-none".to_string())?, None);
+ self.game.load(
+ self.index.generate("lobby-none-none".to_string()).await?,
+ None,
+ );
}
while let Some(p) = self.game.packet_out() {
debug!("-> {p:?}");
@@ -97,7 +111,7 @@ impl State {
async fn handle_command(&mut self, player: PlayerID, command: Command) -> Result<()> {
match command {
Command::Start { spec, timer } => {
- let data = self.index.generate(spec)?;
+ let data = self.index.generate(spec).await?;
self.game.load(data, Some(Duration::from_secs(timer)));
}
Command::End => {
@@ -113,12 +127,22 @@ impl State {
),
})
.ok();
- self.game
- .load(self.index.generate("lobby-none-none".to_string())?, None);
+ self.game.load(
+ self.index.generate("lobby-none-none".to_string()).await?,
+ None,
+ );
}
Command::Reload => {
self.index.reload()?;
}
+ Command::Download { r#type, name } => {
+ let source = match r#type {
+ DownloadType::Map => self.index.read_map(&name).await,
+ DownloadType::Recipes => self.index.read_recipes(&name).await,
+ DownloadType::Demand => self.index.read_demands(&name).await,
+ }?;
+ bail!("{source}");
+ }
Command::List => {
bail!(
"Maps: {:?}\nDemands: {:?}\nRecipes: {:?}",