diff options
Diffstat (limited to 'src/client_main.rs')
| -rw-r--r-- | src/client_main.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/client_main.rs b/src/client_main.rs new file mode 100644 index 0000000..43660d7 --- /dev/null +++ b/src/client_main.rs @@ -0,0 +1,119 @@ +//! # Graf Karto cartographer +//! +//! ### What is it exactly +//! Graf Karto is a table top role playing game (TTRPG) map creation tool that is optimised for real +//! time map interaction. +//! +//! ### Motivation +//! While there are certainly many TTRPG map creation tools for single user and multi user available +//! online and on the market, we felt that most of them lack features or are to unwieldy to seriously +//! consider for real time dungeon drawing, say for instance when drawing a map for an old school +//! revival style game. This is why Graf Karto is optimised for speed above pretty graphical features. +//! The aim is for the user not to have to think much about how they are going to achieve what they are +//! doing and how they are going to make it pretty, but should just be able to *do* it, to have time to +//! worry about other things. This does not mean that all maps created should visually be equivalent to +//! a steaming pile of hot garbage, but if the visuals should try to get in the way, usability and speed +//! takes precedence. + +#![allow(dead_code)] +#![warn(missing_docs)] + +#[macro_use] +extern crate log; + +pub mod client; +pub mod math; +pub mod net; +pub mod server; +pub mod stable_vec; +pub mod transformable; +pub mod world; + +use clap::{App, Arg}; +use server::DEFAULT_PORT; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; +use std::sync::atomic::Ordering; + +fn main() { + pretty_env_logger::init(); + + println!("Graf Karto version: {}", clap::crate_version!()); + let default_port = DEFAULT_PORT.to_string(); + let matches = App::new("Graf Karto") + .version(clap::crate_version!()) + .author(clap::crate_authors!()) + .about(clap::crate_description!()) + .arg(Arg::with_name("connect") + .short("c") + .value_name("SERVER_ADDRESS") + .help("Specify an IP in case an external server should be used (starts a local server if not set).")) + .arg(Arg::with_name("port") + .short("p") + .value_name("SERVER_PORT") + .help("Set the port the server listens on or should listen on. When starting a local server, others may be tried if it cannot be bound.") + .default_value(&default_port)) + .arg(Arg::with_name("ipv4") + .short("v4") + .help("Use virgin IPv4 instead of chad IPv6.. you monster")) + .get_matches(); + + let use_ipv4 = matches.is_present("ipv4"); + let mut server_port = match matches + .value_of("port") + .expect("No port found, eventhough it should have a default value") + .parse::<u16>() + { + Ok(port) => port, + Err(e) => { + error!("Not a valid server port: {:?}", e); + warn!("Using default port {}", DEFAULT_PORT); + DEFAULT_PORT + } + }; + + let server_handle = if !matches.is_present("connect") { + Some({ + let (server_handle, server_running, port) = + server::start_any_port(use_ipv4).expect("Unable to start local server"); + server_port = port; + (server_handle, server_running) + }) + } else { + None + }; + + let server_address = match matches.value_of("connect") { + None => { + // Local server will be started. + if use_ipv4 { + SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), server_port) + } else { + SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), server_port) + } + } + Some(addr) => { + let addrs = (addr, server_port) + .to_socket_addrs() + .expect("Not a valid address"); + let mut addr = None; + for a in addrs { + if use_ipv4 && a.is_ipv4() { + addr = Some(a); + break; + } else if !use_ipv4 && a.is_ipv6() { + addr = Some(a); + break; + } + } + + addr.expect("Could not find a valid ip address on that hostname") + } + }; + + client::run(dbg!(server_address)); + + if let Some((handle, running)) = server_handle { + running.store(false, Ordering::Relaxed); + handle.join().expect("Server thread closed unexpectedly."); + } +} |
