aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/bin/graph.rs77
-rw-r--r--server/src/bin/graph_summary.rs150
-rw-r--r--server/src/commands.rs105
-rw-r--r--server/src/data/mod.rs47
-rw-r--r--server/src/entity/book.rs2
-rw-r--r--server/src/main.rs23
-rw-r--r--server/src/scoreboard.rs36
-rw-r--r--server/src/server.rs7
-rw-r--r--server/src/state.rs11
9 files changed, 109 insertions, 349 deletions
diff --git a/server/src/bin/graph.rs b/server/src/bin/graph.rs
deleted file mode 100644
index 000be9e7..00000000
--- a/server/src/bin/graph.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- Hurry Curry! - a game about cooking
- Copyright (C) 2025 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 anyhow::Result;
-use hurrycurry_protocol::{Demand, ItemIndex, Recipe, RecipeIndex};
-use hurrycurry_server::data::DataIndex;
-
-#[tokio::main]
-async fn main() -> Result<()> {
- let mut index = DataIndex::default();
- index.reload().await?;
-
- println!("digraph {{");
-
- let (data, _, _) = index.generate("5star").await?;
- for i in 0..data.item_names.len() {
- println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
- }
- for (RecipeIndex(ri), recipe) in data.recipes() {
- let (kind, color) = match recipe {
- Recipe::Passive { .. } => ("Passive", "#2bc493"),
- Recipe::Active { .. } => ("Active", "#47c42b"),
- Recipe::Instant { .. } => ("Instant", "#5452d8"),
- };
- println!(
- "r{ri} [label=\"{kind}\\non {}\" shape=box color={color:?} fillcolor={color:?} style=filled]",
- if let Some(tile) = recipe.tile() {
- data.tile_name(tile)
- } else {
- "anything"
- }
- );
- for ItemIndex(input) in recipe.inputs() {
- println!("i{input} -> r{ri}")
- }
- for ItemIndex(output) in recipe.outputs() {
- println!("r{ri} -> i{output}")
- }
- }
-
- for (
- di,
- Demand {
- duration,
- input: ItemIndex(input),
- output,
- points,
- },
- ) in data.demands.iter().enumerate()
- {
- let color = "#c4422b";
- println!(
- "d{di} [label=\"Demand\\ntakes {duration}s\\n{points} points\" shape=box color={color:?} fillcolor={color:?} style=filled]",
- );
- println!("i{input} -> d{di}");
- if let Some(ItemIndex(output)) = output {
- println!("d{di} -> i{output}");
- }
- }
-
- println!("}}");
- Ok(())
-}
diff --git a/server/src/bin/graph_summary.rs b/server/src/bin/graph_summary.rs
deleted file mode 100644
index d22361c0..00000000
--- a/server/src/bin/graph_summary.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- Hurry Curry! - a game about cooking
- Copyright (C) 2025 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 anyhow::Result;
-use hurrycurry_protocol::{ItemIndex, Recipe, TileIndex};
-use hurrycurry_server::data::DataIndex;
-use std::collections::HashSet;
-
-#[tokio::main]
-async fn main() -> Result<()> {
- let mut index = DataIndex::default();
- index.reload().await?;
-
- println!("digraph {{");
-
- let (data, sdata, _) = index.generate("5star").await?;
-
- struct Node {
- inputs: Vec<ItemIndex>,
- outputs: Vec<ItemIndex>,
- tool_item: Option<ItemIndex>,
- tool_tile: Option<TileIndex>,
- instant: bool,
- demand: bool,
- }
-
- let map_items = sdata
- .initial_map
- .iter()
- .flat_map(|(_, (_, i))| *i)
- .collect::<HashSet<_>>();
-
- let mut nodes = Vec::new();
- for r in &data.recipes {
- nodes.push(Node {
- inputs: r.inputs(),
- outputs: r.outputs(),
- tool_item: None,
- tool_tile: r.tile(),
- instant: matches!(r, Recipe::Instant { .. }),
- demand: false,
- })
- }
- for d in &data.demands {
- nodes.push(Node {
- demand: true,
- instant: false,
- inputs: vec![d.input],
- outputs: d.output.into_iter().collect(),
- tool_item: None,
- tool_tile: None,
- })
- }
-
- loop {
- let node_count_before = nodes.len();
-
- let mut has_fdeps = vec![false; data.item_names.len()];
- for n in &nodes {
- for ItemIndex(i) in &n.inputs {
- has_fdeps[*i] = true;
- }
- }
- // Remove demand outputs
- for n in &mut nodes {
- n.outputs.retain(|_item| !n.demand);
- }
- // Remove outputs that are not depended on
- for n in &mut nodes {
- n.outputs.retain(|item| n.demand || has_fdeps[item.0])
- }
- // Remove outputs that exist on the map, like pots and plates
- for n in &mut nodes {
- n.outputs.retain(|item| !map_items.contains(item))
- }
- // Convert map item inputs to tools
- for n in &mut nodes {
- n.inputs.retain(|i| {
- if map_items.contains(i) {
- n.tool_item = Some(*i);
- false
- } else {
- true
- }
- })
- }
- // Remove outputless recipes
- nodes.retain(|n| n.demand || !n.outputs.is_empty());
-
- if nodes.len() == node_count_before {
- break;
- }
- }
-
- let mut items = HashSet::<ItemIndex>::new();
- for n in &nodes {
- items.extend(&n.inputs);
- items.extend(&n.outputs);
- }
-
- for ItemIndex(i) in items {
- println!("i{i} [label=\"{}\"]", data.item_name(ItemIndex(i)))
- }
- for (ni, node) in nodes.iter().enumerate() {
- let color = if node.demand {
- "#c4422b"
- } else if node.instant {
- "#5452d8"
- } else {
- "#47c42b"
- };
- println!(
- "r{ni} [label=\"{}\" shape=box color={color:?} fillcolor={color:?} style=filled]",
- if let Some(tool) = node.tool_tile {
- data.tile_name(tool)
- } else if let Some(tool) = node.tool_item {
- data.item_name(tool)
- } else if node.instant {
- "Combine"
- } else if node.demand {
- "Demand"
- } else {
- "Passive"
- }
- );
- for ItemIndex(input) in &node.inputs {
- println!("i{input} -> r{ni}")
- }
- for ItemIndex(output) in &node.outputs {
- println!("r{ni} -> i{output}")
- }
- }
-
- println!("}}");
- Ok(())
-}
diff --git a/server/src/commands.rs b/server/src/commands.rs
index 460f6581..0e57a013 100644
--- a/server/src/commands.rs
+++ b/server/src/commands.rs
@@ -24,9 +24,7 @@ use crate::{
use anyhow::Result;
use clap::{Parser, ValueEnum};
use hurrycurry_bot::algos::ALGO_CONSTRUCTORS;
-use hurrycurry_protocol::{
- Character, DocumentElement, Menu, Message, PacketC, PlayerClass, PlayerID,
-};
+use hurrycurry_protocol::{Character, Menu, Message, PacketC, PlayerClass, PlayerID};
use std::{fmt::Write, time::Duration};
#[derive(Parser)]
@@ -110,7 +108,7 @@ enum DownloadType {
}
impl Server {
- pub async fn handle_command_parse(
+ pub fn handle_command_parse(
&mut self,
player: PlayerID,
command: &str,
@@ -126,12 +124,11 @@ impl Server {
)
.map_err(|e| TrError::Plain(e.to_string()))?,
&mut replies,
- )
- .await?;
+ )?;
}
Ok(replies)
}
- async fn handle_command(
+ fn handle_command(
&mut self,
player: PlayerID,
command: Command,
@@ -162,8 +159,7 @@ impl Server {
}
let data = self
.index
- .generate(&spec)
- .await
+ .generate_with_book(&spec)
.map_err(|e| TrError::Plain(e.to_string()))?;
self.load(data, timer.map(Duration::from_secs));
if !skip_announce {
@@ -190,8 +186,7 @@ impl Server {
.ok();
self.load(
self.index
- .generate("lobby")
- .await
+ .generate_with_book("lobby")
.map_err(|e| TrError::Plain(e.to_string()))?,
None,
);
@@ -202,8 +197,7 @@ impl Server {
}
self.load(
self.index
- .generate(&self.game.data.current_map)
- .await
+ .generate_with_book(&self.game.data.current_map)
.map_err(|e| TrError::Plain(e.to_string()))?,
None,
);
@@ -211,14 +205,13 @@ impl Server {
Command::ReloadIndex => {
self.index
.reload()
- .await
.map_err(|e| TrError::Plain(e.to_string()))?;
}
- Command::Book => replies.push(PacketC::Menu(Menu::Document(self.data.book.clone()))),
+ Command::Book => replies.push(PacketC::Menu(Menu::Book(self.data.book.clone()))),
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::Map => self.index.read_map(&name),
+ DownloadType::Recipes => self.index.read_recipes(&name),
}
.map_err(|e| TrError::Plain(e.to_string()))?;
replies.push(PacketC::ServerMessage {
@@ -288,45 +281,45 @@ impl Server {
error: false,
});
} else {
- replies.push(PacketC::Menu(Menu::Document(DocumentElement::Document {
- es: vec![DocumentElement::Page {
- es: vec![
- DocumentElement::Par {
- es: vec![DocumentElement::Text {
- s: Message::Translation {
- id: "c.menu.scoreboard".to_string(),
- params: vec![],
- },
- size: 30.,
- bold: false,
- color: None,
- font: None,
- }],
- },
- DocumentElement::List {
- es: board
- .best
- .iter()
- .take(10)
- .enumerate()
- .map(|(place, entry)| DocumentElement::Text {
- s: trm!(
- "c.menu.scoreboard.entry",
- s = (place + 1).to_string(),
- s = entry.score.points.to_string(),
- s = entry.players.clone().join(", ")
- ),
- size: 15.,
- bold: false,
- color: None,
- font: None,
- })
- .collect(),
- },
- ],
- background: None,
- }],
- })));
+ // replies.push(PacketC::Menu(Menu::Document(DocumentElement::Document {
+ // es: vec![DocumentElement::Page {
+ // es: vec![
+ // DocumentElement::Par {
+ // es: vec![DocumentElement::Text {
+ // s: Message::Translation {
+ // id: "c.menu.scoreboard".to_string(),
+ // params: vec![],
+ // },
+ // size: 30.,
+ // bold: false,
+ // color: None,
+ // font: None,
+ // }],
+ // },
+ // DocumentElement::List {
+ // es: board
+ // .best
+ // .iter()
+ // .take(10)
+ // .enumerate()
+ // .map(|(place, entry)| DocumentElement::Text {
+ // s: trm!(
+ // "c.menu.scoreboard.entry",
+ // s = (place + 1).to_string(),
+ // s = entry.score.points.to_string(),
+ // s = entry.players.clone().join(", ")
+ // ),
+ // size: 15.,
+ // bold: false,
+ // color: None,
+ // font: None,
+ // })
+ // .collect(),
+ // },
+ // ],
+ // background: None,
+ // }],
+ // })));
}
} else {
replies.push(PacketC::ServerMessage {
diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs
index b56ea1a1..819d8dd1 100644
--- a/server/src/data/mod.rs
+++ b/server/src/data/mod.rs
@@ -23,19 +23,19 @@ use anyhow::{anyhow, bail, Context, Result};
use demands::generate_demands;
use hurrycurry_bot::algos::ALGO_CONSTRUCTORS;
use hurrycurry_protocol::{
+ book::Book,
glam::{IVec2, Vec2},
- DocumentElement, Gamedata, ItemIndex, MapMetadata, Recipe, TileIndex,
+ Gamedata, ItemIndex, MapMetadata, Recipe, TileIndex,
};
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
- fs::File,
+ fs::{read_to_string, File},
path::PathBuf,
str::FromStr,
sync::{Mutex, RwLock},
time::Duration,
};
-use tokio::fs::read_to_string;
#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)]
#[serde(rename_all = "snake_case")]
@@ -96,7 +96,7 @@ pub struct Serverdata {
pub customer_spawn: Vec2,
pub score_baseline: i64,
pub default_timer: Option<Duration>,
- pub book: DocumentElement,
+ pub book: Book,
pub flags: ServerdataFlags,
}
@@ -122,53 +122,57 @@ fn data_dir() -> PathBuf {
}
impl DataIndex {
- pub async fn load() -> Result<Self> {
+ pub fn load() -> Result<Self> {
let mut s = Self::default();
- s.reload().await?;
+ s.reload()?;
Ok(s)
}
- pub async fn reload(&mut self) -> Result<()> {
+ pub fn reload(&mut self) -> Result<()> {
*self = serde_yml::from_reader(File::open(data_dir().join("index.yaml"))?)?;
Ok(())
}
- pub async fn read_map(&self, name: &str) -> Result<String> {
+ pub fn read_map(&self, name: &str) -> Result<String> {
// 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?)
+ Ok(read_to_string(path)?)
}
- pub async fn read_recipes(&self, name: &str) -> Result<String> {
+ pub 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?)
+ Ok(read_to_string(path)?)
}
- pub async fn generate(&self, map: &str) -> Result<(Gamedata, Serverdata, Entities)> {
+ pub fn generate(&self, map: &str) -> Result<(Gamedata, Serverdata, Entities)> {
let map_in: MapDecl = serde_yml::from_str(
&self
.read_map(map)
- .await
.context(anyhow!("Failed to read map file ({map})"))?,
)
.context(anyhow!("Failed to parse map file ({map})"))?;
let recipes_in = serde_yml::from_str(
&self
.read_recipes(map_in.recipes.as_deref().unwrap_or("default"))
- .await
.context("Failed read recipe file")?,
)
.context("Failed to parse recipe file")?;
- let book = serde_json::from_str(
- &read_to_string(data_dir().join("book.json"))
- .await
- .context("Failed to read book file")?,
+
+ build_data(&self.maps, map.to_string(), map_in, recipes_in)
+ }
+ pub fn generate_with_book(&self, map: &str) -> Result<(Gamedata, Serverdata, Entities)> {
+ let (gd, mut sd, es) = self.generate(map)?;
+ sd.book = self.read_book()?;
+ Ok((gd, sd, es))
+ }
+ pub fn read_book(&self) -> Result<Book> {
+ serde_json::from_str(
+ &read_to_string(data_dir().join("book.json")).context("Failed to read book file")?,
)
- .context("Failed to parse book file")?;
- build_data(&self.maps, map.to_string(), map_in, recipes_in, book)
+ .context("Failed to parse book file")
}
}
@@ -177,7 +181,6 @@ pub fn build_data(
map_name: String,
map_in: MapDecl,
recipes_in: Vec<RecipeDecl>,
- book: DocumentElement,
) -> Result<(Gamedata, Serverdata, Entities)> {
let reg = ItemTileRegistry::default();
let mut recipes = Vec::new();
@@ -330,7 +333,7 @@ pub fn build_data(
flags: map_in.flags,
customer_spawn,
default_timer,
- book,
+ book: Book::default(),
score_baseline: map_in.score_baseline,
},
entities,
diff --git a/server/src/entity/book.rs b/server/src/entity/book.rs
index 54dc4d2c..566eb0a9 100644
--- a/server/src/entity/book.rs
+++ b/server/src/entity/book.rs
@@ -32,7 +32,7 @@ impl Entity for Book {
) -> Result<bool, TrError> {
if pos == Some(self.0) {
if let Some(r) = c.replies {
- r.push(PacketC::Menu(Menu::Document(c.serverdata.book.clone())));
+ r.push(PacketC::Menu(Menu::Book(c.serverdata.book.clone())));
}
return Ok(true);
}
diff --git a/server/src/main.rs b/server/src/main.rs
index 3cc6785a..ef397c7d 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -159,8 +159,8 @@ async fn run(args: Args) -> anyhow::Result<()> {
let (tx, rx) = broadcast::channel::<PacketC>(128 * 1024);
- let mut state = Server::new(tx).await?;
- state.load(state.index.generate("lobby").await?, None);
+ let mut state = Server::new(tx)?;
+ state.load(state.index.generate_with_book("lobby")?, None);
let state = Arc::new(RwLock::new(state));
#[cfg(feature = "register")]
@@ -197,7 +197,7 @@ async fn run(args: Args) -> anyhow::Result<()> {
let mut tick = interval(Duration::from_secs_f32(dt));
loop {
tick.tick().await;
- if let Err(e) = state.write().await.tick_outer(dt).await {
+ if let Err(e) = state.write().await.tick_outer(dt) {
warn!("Tick failed: {e}");
}
}
@@ -348,19 +348,26 @@ mod test {
#[test]
fn run() {
- harness(async { Server::new(broadcast::channel(1024).0).await.unwrap() });
+ harness(async { Server::new(broadcast::channel(1024).0).unwrap() });
}
#[test]
fn map_load() {
harness(async {
- let mut s = Server::new(broadcast::channel(1024).0).await.unwrap();
- s.load(s.index.generate("lobby").await.unwrap(), None);
+ let mut s = Server::new(broadcast::channel(1024).0).unwrap();
+ s.load(s.index.generate("5star").unwrap(), None);
+ });
+ }
+ #[test]
+ fn map_load_book() {
+ harness(async {
+ let mut s = Server::new(broadcast::channel(1024).0).unwrap();
+ s.load(s.index.generate_with_book("lobby").unwrap(), None);
});
}
#[test]
fn tick() {
harness(async {
- let mut s = Server::new(broadcast::channel(1024).0).await.unwrap();
+ let mut s = Server::new(broadcast::channel(1024).0).unwrap();
for _ in 0..100 {
s.tick(0.1);
}
@@ -369,7 +376,7 @@ mod test {
#[test]
fn packet_sender_verif() {
harness(async {
- let mut s = Server::new(broadcast::channel(1024).0).await.unwrap();
+ let mut s = Server::new(broadcast::channel(1024).0).unwrap();
for (conn, p) in [
PacketS::Effect {
diff --git a/server/src/scoreboard.rs b/server/src/scoreboard.rs
index 60b9356c..e97e22b2 100644
--- a/server/src/scoreboard.rs
+++ b/server/src/scoreboard.rs
@@ -17,36 +17,27 @@
*/
use anyhow::Result;
use directories::ProjectDirs;
-use hurrycurry_protocol::Score;
+use hurrycurry_protocol::{Score, Scoreboard, ScoreboardEntry};
use log::warn;
use serde::{Deserialize, Serialize};
-use std::{cmp::Reverse, collections::HashMap};
-use tokio::{
+use std::{
+ cmp::Reverse,
+ collections::HashMap,
fs::{create_dir_all, read_to_string, rename, File},
- io::AsyncWriteExt,
+ io::Write,
};
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct ScoreboardStore {
maps: HashMap<String, Scoreboard>,
}
-#[derive(Debug, Serialize, Deserialize, Clone, Default)]
-pub struct Scoreboard {
- pub plays: usize,
- pub best: Vec<ScoreboardEntry>,
-}
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct ScoreboardEntry {
- pub players: Vec<String>,
- pub score: Score,
-}
fn project_dirs() -> Option<ProjectDirs> {
ProjectDirs::from("org", "hurrycurry", "hurrycurry")
}
impl ScoreboardStore {
- pub async fn load() -> Result<Self> {
+ pub fn load() -> Result<Self> {
let Some(dir) = project_dirs() else {
warn!("scoreboard load skipped; no data dir for this platform");
return Ok(Self::default());
@@ -54,24 +45,21 @@ impl ScoreboardStore {
// TOCTOU because its easier that way
let path = dir.data_dir().join("scoreboards.json");
if !path.exists() {
- create_dir_all(dir.data_dir()).await?;
- ScoreboardStore::default().save().await?;
+ create_dir_all(dir.data_dir())?;
+ ScoreboardStore::default().save()?;
}
- let s = read_to_string(path).await?;
+ let s = read_to_string(path)?;
Ok(serde_json::from_str(&s)?)
}
- pub async fn save(&self) -> Result<()> {
+ pub fn save(&self) -> Result<()> {
let Some(dir) = project_dirs() else {
warn!("scoreboard save skipped; no data dir for this platform");
return Ok(());
};
let path = dir.data_dir().join("scoreboards.json");
let buffer_path = dir.data_dir().join("scoreboards.json~");
- File::create(&buffer_path)
- .await?
- .write_all(serde_json::to_string(self)?.as_bytes())
- .await?;
- rename(buffer_path, path).await?;
+ File::create(&buffer_path)?.write_all(serde_json::to_string(self)?.as_bytes())?;
+ rename(buffer_path, path)?;
Ok(())
}
pub fn get<'a>(&'a self, map: &str) -> Option<&'a Scoreboard> {
diff --git a/server/src/server.rs b/server/src/server.rs
index 2fe0be17..f97ca69c 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -314,12 +314,10 @@ impl GameServerExt for Game {
}
impl Server {
- pub async fn new(tx: Sender<PacketC>) -> Result<Self> {
+ pub fn new(tx: Sender<PacketC>) -> Result<Self> {
Ok(Self {
game: Game::default(),
- index: DataIndex::load()
- .await
- .context("Failed to load data index")?,
+ index: DataIndex::load().context("Failed to load data index")?,
tx,
start_pause_timer: 0.,
packet_out: VecDeque::new(),
@@ -332,7 +330,6 @@ impl Server {
packet_loopback: VecDeque::new(),
last_movement_update: HashMap::default(),
scoreboard: ScoreboardStore::load()
- .await
.context("Failed to load scoreboards")?,
editor_address: None,
paused: false,
diff --git a/server/src/state.rs b/server/src/state.rs
index 5eb4059a..19c38fd2 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -21,7 +21,7 @@ use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID};
use log::{debug, info, trace};
impl Server {
- pub async fn tick_outer(&mut self, dt: f32) -> anyhow::Result<()> {
+ pub fn tick_outer(&mut self, dt: f32) -> anyhow::Result<()> {
if self.start_pause_timer > 0. {
self.start_pause_timer -= dt
}
@@ -46,8 +46,8 @@ impl Server {
if !self.paused {
let r = self.tick(dt);
if let Some((name, timer)) = r {
- self.scoreboard.save().await?;
- self.load(self.index.generate(&name).await?, timer);
+ self.scoreboard.save()?;
+ self.load(self.index.generate_with_book(&name)?, timer);
}
}
while let Some(p) = self.packet_out.pop_front() {
@@ -78,7 +78,7 @@ impl Server {
player,
..
} if let Some(command) = text.strip_prefix("/") => {
- match self.handle_command_parse(*player, command).await {
+ match self.handle_command_parse(*player, command) {
Ok(packets) => return Ok(packets),
Err(e) => {
return Ok(vec![PacketC::ServerMessage {
@@ -116,8 +116,7 @@ impl Server {
.ok();
self.load(
self.index
- .generate("lobby")
- .await
+ .generate_with_book("lobby")
.map_err(|m| tre!("s.error.map_load", s = format!("{m}")))?,
None,
);