diff options
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/components/equipment.rs | 20 | ||||
| -rw-r--r-- | src/config.rs | 19 | ||||
| -rw-r--r-- | src/main.rs | 45 | ||||
| -rw-r--r-- | src/parameter.rs | 8 | ||||
| -rw-r--r-- | src/server/address.rs | 42 | ||||
| -rw-r--r-- | src/server/mod.rs | 1 | ||||
| -rw-r--r-- | src/util.rs | 5 | ||||
| -rw-r--r-- | todo.md | 1 |
9 files changed, 88 insertions, 54 deletions
@@ -16,3 +16,4 @@ rand = "0.7" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } ctrlc = { version = "3.1", features = ["termination"] } +structopt = "0.3" diff --git a/src/components/equipment.rs b/src/components/equipment.rs index c19563f..8f7b9ab 100644 --- a/src/components/equipment.rs +++ b/src/components/equipment.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use serde_json::{json, Value}; +use serde_json::Value; use specs::{ Component, HashMapStorage @@ -21,12 +21,6 @@ impl Slot { _ => None } } - pub fn to_string(&self) -> String { - match self { - Self::Hand => "hand", - Self::Body => "body" - }.to_string() - } } @@ -44,12 +38,6 @@ impl Stat { _ => None } } - pub fn to_string(&self) -> String { - match self { - Self::Strength => "strength", - Self::Defence => "defence" - }.to_string() - } } @@ -73,12 +61,6 @@ impl Equippable { .collect::<Option<HashMap<Stat, i64>>>()? }) } - pub fn to_json(&self) -> Value { - json!({ - "slot": self.slot.to_string(), - "stats": self.stats.iter().map(|(k, v)| (k.to_string(), *v)).collect::<HashMap<String, i64>>() - }) - } } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..9d2c480 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,19 @@ + +use structopt::StructOpt; +use std::path::PathBuf; +use crate::Address; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Rustifarm", about = "Asciifarm server in Rust")] +pub struct Config { + + #[structopt(short, long, help="A server type and address. Allowed server types: 'inet', 'unix', 'abstract'. Example: \"inet:127.0.0.1:1234\" or \"abstract:rustifarm\"")] + pub address: Option<Vec<Address>>, + + #[structopt(short, long, env="ASCIIFARM_CONTENT_DIR", help="The directory in which the content specifying the world is (maps/encyclopaedia)")] + pub content_dir: Option<PathBuf>, + + #[structopt(short, long, env="ASCIIFARM_SAVE_DIR", help="The directory in which the savegames are")] + pub save_dir: Option<PathBuf>, + +} diff --git a/src/main.rs b/src/main.rs index 68e0f50..b55c6a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ use std::thread::sleep; use std::time::Duration; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use std::fs; use serde_json; +use structopt::StructOpt; mod server; mod gameserver; @@ -33,6 +34,7 @@ mod world; mod sprite; mod timestamp; mod purgatory; +mod config; use self::{ pos::Pos, @@ -42,14 +44,11 @@ use self::{ sprite::Sprite, template::Template, encyclopedia::Encyclopedia, - timestamp::Timestamp -}; - -use self::{ + timestamp::Timestamp, + gameserver::GameServer, - server::unixserver::UnixServer, - server::tcpserver::TcpServer, server::Server, + server::address::Address, persistence::FileStorage, controls::Action, worldloader::WorldLoader, @@ -61,22 +60,32 @@ use self::{ fn main() -> Result<()>{ - let mut servers: Vec<Box<dyn Server>> = Vec::new(); - - let addr = Path::new("\0rustifarm"); - let unixserver = UnixServer::new(&addr)?; - servers.push(Box::new(unixserver)); + let config = config::Config::from_args(); - let addr = "127.0.0.1:1234".parse()?; - let inetserver = TcpServer::new(&addr)?; - servers.push(Box::new(inetserver)); + let adresses = config.address + .unwrap_or(vec!["abstract:rustifarm".parse()?, "inet:127.0.0.1:1234".parse()?]); + println!("adresses: {:?}", adresses); + let servers: Vec<Box<dyn Server>> = + adresses + .iter() + .map(|a| a.to_server().unwrap()) + .collect(); let mut gameserver = GameServer::new(servers); - let content_dir = PathBuf::new().join(std::env::var("CARGO_MANIFEST_DIR").unwrap_or(".".to_string())).join("content/"); + let content_dir = config.content_dir.unwrap_or( + PathBuf::new() + .join(std::env::var("CARGO_MANIFEST_DIR").unwrap_or(".".to_string())) + .join("content/") + ); + println!("content directory: {:?}", content_dir); let loader = WorldLoader::new(content_dir.join("maps")); - let storage = FileStorage::new(FileStorage::savedir().expect("couldn't find any save directory")); + let save_dir = config.save_dir.unwrap_or( + FileStorage::savedir().expect("couldn't find any save directory") + ); + println!("save directory: {:?}", content_dir); + let storage = FileStorage::new(save_dir); let encyclopedia = Encyclopedia::from_json( serde_json::from_str( @@ -146,3 +155,5 @@ fn main() -> Result<()>{ } + + diff --git a/src/parameter.rs b/src/parameter.rs index 5466ce6..ed445b3 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -69,12 +69,12 @@ parameters!( Pos (Pos) pos, v (Pos::from_json(v)?) (json!(v)); Float (f64) float, v (v.as_f64()?) (json!(v)); Template (Template) template, v (Template::from_json(v).ok()?) (v.to_json()); - Action (ItemAction) action, v (ItemAction::from_json(v)?) (panic!("item actions can't be serialized")); - Interaction (Interactable) interaction, v (Interactable::from_json(v)?) (panic!("interactions can't be serialized")); + Action (ItemAction) action, _v (ItemAction::from_json(_v)?) (panic!("item actions can't be serialized")); + Interaction (Interactable) interaction, _v (Interactable::from_json(_v)?) (panic!("interactions can't be serialized")); Bool (bool) bool, v (v.as_bool()?) (json!(v)); - List (Vec<Parameter>) list, v + List (Vec<Parameter>) list, _v ({ - v + _v .as_array()? .iter() .map(|item| Parameter::guess_from_json(item)) diff --git a/src/server/address.rs b/src/server/address.rs index 3d8e59f..9fb7bea 100644 --- a/src/server/address.rs +++ b/src/server/address.rs @@ -1,19 +1,45 @@ +use std::path::PathBuf; use std::net::SocketAddr; -use std::path::Path; +use std::str::FromStr; use crate::{ Result, - aerr + aerr, + util::AnyError }; use super::tcpserver::TcpServer; use super::unixserver::UnixServer; use super::Server; -pub fn server_from_address(typename: &str, text: &str) -> Result<Box<dyn Server>> { - match typename { - "inet" => Ok(Box::new(TcpServer::new(&text.parse()?)?)), - "unix" => Ok(Box::new(UnixServer::new(Path::new(text))?)), - "abstract" => Ok(Box::new(UnixServer::new(Path::new(&format!("\0{}", text)))?)), - _ => Err(aerr!("Invalid address type")) +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Address { + Inet(SocketAddr), + Unix(PathBuf) +} + +impl Address { + pub fn to_server(&self) -> Result<Box<dyn Server>> { + match self { + Address::Inet(addr) => Ok(Box::new(TcpServer::new(addr)?)), + Address::Unix(path) => Ok(Box::new(UnixServer::new(path)?)), + } + } +} + +impl FromStr for Address { + type Err = AnyError; + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + let parts: Vec<&str> = s.splitn(2, ':').collect(); + if parts.len() != 2 { + return Err(aerr!("Address string has the wrong length!")); + } + let typename = parts[0]; + let text = parts[1]; + match typename { + "inet" => Ok(Address::Inet(text.parse()?)), + "unix" => Ok(Address::Unix(PathBuf::new().join(text))), + "abstract" => Ok(Address::Unix(PathBuf::new().join(&format!("\0{}", text)))), + _ => Err(aerr!(&format!("'{}' is not a valid address type", typename))) + } } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 131eb19..71b1f96 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -2,6 +2,7 @@ use std::io; pub mod tcpserver; pub mod unixserver; +pub mod address; mod streamconnection; diff --git a/src/util.rs b/src/util.rs index db572c6..9b46d42 100644 --- a/src/util.rs +++ b/src/util.rs @@ -41,11 +41,6 @@ macro_rules! aerr { ($description:expr) => {Box::new(crate::util::AError::new($description))} } -#[macro_export] -macro_rules! err { - ($description:expr) => {Err(crate::aerr!($description))} -} - #[macro_export] macro_rules! hashmap { @@ -3,7 +3,6 @@ - make readme - more tests -- command line options - private rooms - timer resource? - log world events to player |
