aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/commands.rs91
-rw-r--r--server/src/message.rs25
-rw-r--r--server/src/state.rs2
3 files changed, 77 insertions, 41 deletions
diff --git a/server/src/commands.rs b/server/src/commands.rs
index 478d88e3..feb6ab65 100644
--- a/server/src/commands.rs
+++ b/server/src/commands.rs
@@ -17,10 +17,11 @@
*/
use crate::{
entity::{bot::BotDriver, tutorial::Tutorial},
+ message::TrError,
server::Server,
- trm,
+ tre, trm,
};
-use anyhow::{anyhow, bail, Result};
+use anyhow::Result;
use clap::{Parser, ValueEnum};
use hurrycurry_bot::algos::ALGO_CONSTRUCTORS;
use hurrycurry_protocol::{Menu, Message, PacketC, PlayerClass, PlayerID};
@@ -103,16 +104,17 @@ impl Server {
&mut self,
player: PlayerID,
command: &str,
- ) -> Result<Vec<PacketC>> {
+ ) -> Result<Vec<PacketC>, TrError> {
let mut replies = Vec::new();
for line in command.split("\n") {
self.handle_command(
player,
Command::try_parse_from(
shlex::split(line)
- .ok_or(anyhow!("quoting invalid"))?
+ .ok_or(tre!("s.error.quoting_invalid"))?
.into_iter(),
- )?,
+ )
+ .map_err(|e| TrError::Plain(e.to_string()))?,
&mut replies,
)
.await?;
@@ -124,7 +126,7 @@ impl Server {
player: PlayerID,
command: Command,
replies: &mut Vec<PacketC>,
- ) -> Result<()> {
+ ) -> Result<(), TrError> {
match command {
Command::Start { spec, timer } => {
if !self.game.lobby {
@@ -136,7 +138,7 @@ impl Server {
.game
.players
.get(&player)
- .ok_or(anyhow!("player missing"))?
+ .ok_or(tre!("s.error.no_player"))?
.name
.clone()
),
@@ -144,7 +146,11 @@ impl Server {
})
.ok();
}
- let data = self.index.generate(&spec).await?;
+ let data = self
+ .index
+ .generate(&spec)
+ .await
+ .map_err(|e| TrError::Plain(e.to_string()))?;
self.load(data, timer.map(Duration::from_secs));
}
Command::End => {
@@ -156,42 +162,59 @@ impl Server {
.game
.players
.get(&player)
- .ok_or(anyhow!("player missing"))?
+ .ok_or(tre!("s.error.no_player"))?
.name
.clone()
),
error: false,
})
.ok();
- self.load(self.index.generate("lobby").await?, None);
+ self.load(
+ self.index
+ .generate("lobby")
+ .await
+ .map_err(|e| TrError::Plain(e.to_string()))?,
+ None,
+ );
}
Command::Reload => {
if self.count_chefs() > 1 {
- bail!("must be at most one player to reload");
+ return Err(tre!("s.error.must_be_alone"));
}
self.load(
- self.index.generate(&self.game.data.current_map).await?,
+ self.index
+ .generate(&self.game.data.current_map)
+ .await
+ .map_err(|e| TrError::Plain(e.to_string()))?,
None,
);
}
Command::ReloadIndex => {
- self.index.reload().await?;
+ self.index
+ .reload()
+ .await
+ .map_err(|e| TrError::Plain(e.to_string()))?;
}
Command::Book => replies.push(PacketC::Menu(Menu::Book)),
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,
- }?;
- bail!("{source}");
+ }
+ .map_err(|e| TrError::Plain(e.to_string()))?;
+ replies.push(PacketC::ServerMessage {
+ message: Message::Text(source),
+ error: false,
+ });
}
- Command::List => {
- bail!(
+ Command::List => replies.push(PacketC::ServerMessage {
+ message: Message::Text(format!(
"Maps: {:?}\nRecipes: {:?}",
self.index.maps.keys().collect::<Vec<_>>(),
self.index.recipes
- )
- }
+ )),
+ error: false,
+ }),
Command::Effect { name } => {
self.tx.send(PacketC::Effect { name, player }).ok();
}
@@ -200,7 +223,7 @@ impl Server {
.game
.data
.get_item_by_name(&name)
- .ok_or(anyhow!("unknown item"))?;
+ .ok_or(tre!("s.error.item_not_found", s = name))?;
self.tx
.send(PacketC::Communicate {
player,
@@ -213,7 +236,7 @@ impl Server {
let (aname, cons) = ALGO_CONSTRUCTORS
.iter()
.find(|(name, _)| *name == algo.as_str())
- .ok_or(anyhow!("algo name unknown"))?;
+ .ok_or(tre!("s.error.algo_not_found", s = algo))?;
let algo = cons();
self.entities.push(Box::new(BotDriver::new(
format!("{}-bot", name.unwrap_or((*aname).to_owned())),
@@ -235,7 +258,10 @@ impl Server {
)
.unwrap();
}
- bail!("{o}");
+ replies.push(PacketC::ServerMessage {
+ message: Message::Text(o),
+ error: false,
+ });
}
}
Command::Info { map } => {
@@ -244,20 +270,21 @@ impl Server {
.index
.maps
.get(mapname)
- .ok_or(anyhow!("no information available"))?;
- bail!(
- "{:?}\nRecommended player count: {}\nDifficulty: {}",
- info.name,
- info.difficulty,
- info.players
- )
+ .ok_or(tre!("s.error.no_info"))?;
+ replies.push(PacketC::ServerMessage {
+ message: Message::Text(format!(
+ "{:?}\nRecommended player count: {}\nDifficulty: {}",
+ info.name, info.difficulty, info.players
+ )),
+ error: false,
+ });
}
Command::StartTutorial { item } => {
let item = self
.game
.data
.get_item_by_name(&item)
- .ok_or(anyhow!("unknown item"))?;
+ .ok_or(tre!("s.error.item_not_found", s = item))?;
#[cfg(not(test))] // TODO rust-analyser does not undestand trait upcasting
if self
.entities
@@ -268,7 +295,7 @@ impl Server {
})
.is_some()
{
- bail!("Tutorial already running")
+ return Err(tre!("s.error.tutorial_already_running"));
}
self.entities.push(Box::new(Tutorial::new(player, item)));
}
@@ -281,7 +308,7 @@ impl Server {
{
tutorial.ended = true;
} else {
- bail!("No tutorial running")
+ return Err(tre!("s.error.tutorial_no_running"));
}
}
Command::TranslateMessage {
diff --git a/server/src/message.rs b/server/src/message.rs
index c248fff8..79c004a2 100644
--- a/server/src/message.rs
+++ b/server/src/message.rs
@@ -46,28 +46,37 @@ macro_rules! trm_param {
};
}
-pub struct TrError {
- pub id: &'static str,
- pub params: Vec<Message>,
+pub enum TrError {
+ Tr {
+ id: &'static str,
+ params: Vec<Message>,
+ },
+ Plain(String),
}
impl From<TrError> for Message {
fn from(value: TrError) -> Self {
- Self::Translation {
- id: value.id.to_owned(),
- params: value.params,
+ match value {
+ TrError::Tr { id, params } => Self::Translation {
+ id: id.to_owned(),
+ params,
+ },
+ TrError::Plain(s) => Self::Text(s),
}
}
}
impl Debug for TrError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{} {:?}", tr(self.id), self.params)
+ match self {
+ TrError::Tr { id, params } => write!(f, "{} {:?}", tr(id), params),
+ TrError::Plain(s) => write!(f, "{s}"),
+ }
}
}
#[macro_export]
macro_rules! tre {
($id:literal $(, $typ:ident = $param:expr)*) => {
- crate::message::TrError {
+ crate::message::TrError::Tr {
id: $id,
params: vec![$(crate::tre_param!($typ, $param)),*]
}
diff --git a/server/src/state.rs b/server/src/state.rs
index 068b45a8..20e2bf80 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -59,7 +59,7 @@ impl Server {
Ok(packets) => return Ok(packets),
Err(e) => {
return Ok(vec![PacketC::ServerMessage {
- message: Message::Text(format!("{e}")), // TODO localize
+ message: e.into(),
error: true,
}]);
}