planet-wars/backend/src/main.rs

171 lines
4.7 KiB
Rust
Raw Normal View History

#![feature(proc_macro_hygiene, async_closure, decl_macro)]
2020-03-25 21:14:26 +00:00
extern crate serde;
#[macro_use]
extern crate serde_derive;
2020-04-01 18:49:50 +00:00
#[macro_use]
extern crate serde_json;
2019-09-14 11:16:16 +00:00
2020-03-24 17:24:20 +00:00
extern crate async_std;
2019-09-14 11:16:16 +00:00
extern crate futures;
extern crate mozaic;
extern crate rand;
2020-11-14 17:21:27 +00:00
extern crate figment;
2019-11-15 18:01:44 +00:00
extern crate tracing;
extern crate tracing_futures;
extern crate tracing_subscriber;
2020-03-25 21:14:26 +00:00
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
#[macro_use]
extern crate educe;
2020-03-27 16:32:18 +00:00
2020-11-14 17:21:27 +00:00
use figment::{providers::{Serialized, Env}};
2020-03-24 17:24:20 +00:00
use tracing_subscriber::{EnvFilter, FmtSubscriber};
2019-09-14 11:16:16 +00:00
use std::net::SocketAddr;
2020-03-24 17:24:20 +00:00
2020-04-09 21:03:36 +00:00
use mozaic::modules::game;
2019-09-14 11:16:16 +00:00
2020-03-24 17:24:20 +00:00
use futures::executor::ThreadPool;
use futures::future::FutureExt;
2019-09-14 11:16:16 +00:00
2020-03-24 17:24:20 +00:00
use mozaic::graph;
use mozaic::modules::*;
mod planetwars;
2020-03-25 21:14:26 +00:00
mod routes;
mod util;
2020-03-28 18:07:55 +00:00
use util::Games;
2020-04-01 21:03:18 +00:00
use util::COLOURS;
2020-03-25 21:14:26 +00:00
use rocket::fairing::AdHoc;
2020-03-25 21:14:26 +00:00
use rocket_contrib::templates::tera::{self, Value};
2020-04-09 21:03:36 +00:00
use rocket_contrib::templates::{Engines, Template};
2020-03-25 21:14:26 +00:00
use std::collections::HashMap;
2020-11-14 17:21:27 +00:00
/// Config for the planetwars server
#[derive(Deserialize, Serialize, Debug)]
pub struct PWConfig {
host_name: String,
address: String,
port: u16,
}
impl Default for PWConfig {
fn default() -> Self {
Self {
host_name: String::from("localhost"),
address: String::from("0.0.0.0"),
port: 8000,
}
}
}
2020-04-09 20:57:12 +00:00
/// Calculate viewbox from array of points (used in map preview), added to Tera engine.
/// So this function can be called in template.
2020-06-14 20:20:08 +00:00
fn calc_viewbox(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
2020-03-25 21:14:26 +00:00
let mut min_x = std::f64::MAX;
let mut min_y = std::f64::MAX;
let mut max_x = std::f64::MIN;
let mut max_y = std::f64::MIN;
for v in value.as_array().unwrap() {
let x = v.get("x").and_then(|v| v.as_f64()).unwrap();
let y = v.get("y").and_then(|v| v.as_f64()).unwrap();
2020-04-09 21:03:36 +00:00
if x < min_x {
min_x = x;
}
if x > max_x {
max_x = x;
}
if y < min_y {
min_y = y;
}
if y > max_y {
max_y = y;
}
2020-03-25 21:14:26 +00:00
}
2020-04-09 21:03:36 +00:00
return Ok(Value::String(format!(
"{} {} {} {}",
min_x - 3.,
min_y - 3.,
(max_x - min_x) + 6.,
(max_y - min_y) + 6.
)));
2020-03-25 21:14:26 +00:00
}
2020-04-09 20:57:12 +00:00
/// Get's the right colour for planets
2020-06-14 20:20:08 +00:00
fn get_colour(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
2020-04-09 21:03:36 +00:00
return Ok(Value::String(
COLOURS[value.as_u64().unwrap_or(0) as usize].to_string(),
));
2019-09-14 11:16:16 +00:00
}
fn get_host_name(host_name: &str) -> impl Fn(&HashMap<String, Value>) -> tera::Result<Value> + Sync + Send {
let host_name = host_name.to_string();
move |_| Ok(Value::String(host_name.clone()))
}
2020-04-09 20:57:12 +00:00
/// Async main function, starting logger, graph and rocket
#[rocket::launch]
2020-06-20 09:21:41 +00:00
async fn rocket() -> rocket::Rocket {
2020-03-27 17:35:56 +00:00
let fut = graph::set_default();
let sub = FmtSubscriber::builder()
.with_env_filter(EnvFilter::from_default_env())
.finish();
tracing::subscriber::set_global_default(sub).unwrap();
let pool = ThreadPool::builder().create().unwrap();
2020-03-27 17:35:56 +00:00
pool.spawn_ok(fut.map(|_| ()));
2020-04-01 18:49:50 +00:00
let gm = create_game_manager("0.0.0.0:9142", pool.clone()).await;
async_std::task::sleep(std::time::Duration::from_millis(200)).await;
2020-03-27 17:35:56 +00:00
2020-03-25 21:14:26 +00:00
let mut routes = Vec::new();
routes::fuel(&mut routes);
2020-11-14 17:21:27 +00:00
let figment = rocket::Config::figment()
.merge(Serialized::defaults(PWConfig::default())) // Extend but not overwrite
.merge(Env::prefixed("PW_")); // Overwrite
rocket::custom(figment)
2020-03-27 17:35:56 +00:00
.manage(gm)
.manage(pool)
2020-03-28 18:07:55 +00:00
.manage(Games::new())
2020-11-14 17:21:27 +00:00
.attach(AdHoc::config::<PWConfig>()) // Manage the config
.mount("/", routes)
.attach(AdHoc::on_attach("Assets Config", async move |rocket| {
2020-11-14 17:21:27 +00:00
let pw_config = rocket.figment().extract::<PWConfig>().unwrap_or_default();
println!("PW Config {:?}", pw_config);
let host_name = pw_config.host_name.clone();
let tera = Template::custom(move |engines: &mut Engines| {
engines.tera.register_filter("calc_viewbox", calc_viewbox);
engines.tera.register_filter("get_colour", get_colour);
engines.tera.register_function("get_host_name", get_host_name(&host_name));
});
Ok(rocket.attach(tera))
}))
2020-03-25 21:14:26 +00:00
}
2020-04-09 20:57:12 +00:00
/// Creates the actual game_manager
/// Opening tcp socket etc..
2020-04-01 18:49:50 +00:00
async fn create_game_manager(tcp: &str, pool: ThreadPool) -> game::Manager {
2020-03-27 17:35:56 +00:00
let addr = tcp.parse::<SocketAddr>().unwrap();
2020-03-24 17:24:20 +00:00
let (gmb, handle) = game::Manager::builder(pool.clone());
pool.spawn_ok(handle.map(|_| {println!("I'm done")}));
2020-03-24 17:24:20 +00:00
let ep = TcpEndpoint::new(addr, pool.clone());
2019-09-14 11:16:16 +00:00
2020-03-27 17:35:56 +00:00
let gmb = gmb.add_endpoint(ep, "TCP endpoint");
gmb.build("games/games.json", pool).await.unwrap()
2019-09-14 11:16:16 +00:00
}