aboutsummaryrefslogtreecommitdiff
path: root/src/client_main.rs
blob: 3e0a4361f59bdd849f3ae5be0042a6b436ad7002 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! # 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};

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, port) =
                server::start_any_port(use_ipv4).expect("Unable to start local server");
            server_port = port;
            server_handle
        })
    } 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) => (addr, server_port)
            .to_socket_addrs()
            .expect("Not a valid address")
            .next()
            .expect("Hostname not registered."),
    };

    client::run(server_address);

    if let Some(handle) = server_handle {
        handle.join().expect("Server thread closed unexpectedly.");
    }
}