164 lines
4.9 KiB
Rust
164 lines
4.9 KiB
Rust
#[macro_use]
|
|
extern crate rocket;
|
|
#[macro_use]
|
|
extern crate lazy_static;
|
|
|
|
use clap::Parser;
|
|
|
|
use rocket::fs::{relative, FileServer};
|
|
use rocket::response::stream::{Event, EventStream};
|
|
use rocket_dyn_templates::Template;
|
|
|
|
use std::{
|
|
collections::HashMap,
|
|
mem::drop,
|
|
sync::{mpsc, Mutex, RwLock},
|
|
};
|
|
|
|
mod names;
|
|
mod rooms;
|
|
mod templates;
|
|
|
|
lazy_static! {
|
|
static ref ARGS: Args = Args::parse();
|
|
static ref ROOMS: Mutex<HashMap<String, rooms::Room>> = Mutex::new(HashMap::new());
|
|
/// String is the room list
|
|
static ref PLAYS: Mutex<HashMap<String, Vec<rooms::Board>>> = Mutex::new(HashMap::new());
|
|
}
|
|
|
|
/*
|
|
* Config options
|
|
*/
|
|
#[derive(Parser, Debug)]
|
|
#[clap(about, version, author)]
|
|
struct Args {
|
|
// Port number for server
|
|
#[clap(short, long, default_value_t = 8000)]
|
|
port: u16,
|
|
// this is here so that it shows up in help, it's actually used in templates.rs
|
|
// sucks
|
|
#[clap(short, long, default_value = "http://127.0.0.1:8000")]
|
|
base_url: String,
|
|
}
|
|
|
|
#[launch]
|
|
fn rocket() -> _ {
|
|
let mut config = rocket::Config::default();
|
|
config.port = ARGS.port;
|
|
rocket::custom(config)
|
|
.attach(Template::fairing())
|
|
.mount("/", FileServer::from(relative!("static")))
|
|
.mount("/", routes![index, room, stream, play])
|
|
}
|
|
|
|
/*
|
|
* handles creating rooms, player counts and
|
|
*/
|
|
#[get("/?<roomname>")]
|
|
async fn index(mut roomname: String) -> Template {
|
|
// remove whitespace from roomname
|
|
roomname = roomname.split_whitespace().collect();
|
|
// generate roomname if there is none yet
|
|
if roomname.chars().count() == 0 {
|
|
roomname = names::get_random_name().await;
|
|
print!("{}", roomname)
|
|
}
|
|
// lock list of rooms
|
|
let mut rooms = ROOMS.lock().unwrap();
|
|
// do this if there are already people in the room
|
|
// first let the new player join and then lock the room for others
|
|
if rooms.contains_key(&roomname) {
|
|
let mut room = rooms.get_mut(&roomname).unwrap();
|
|
if room.full {
|
|
drop(rooms);
|
|
return templates::get_back_to_home(&roomname);
|
|
}
|
|
room.full = true;
|
|
let templ = templates::join_room(&roomname, room.token);
|
|
drop(rooms);
|
|
return templ;
|
|
}
|
|
//create a new room if it doesn't exist yet
|
|
else {
|
|
// create new room
|
|
let room = rooms::Room::new();
|
|
let templ = templates::join_new_room(&roomname, room.token);
|
|
rooms.insert(roomname.to_string(), room);
|
|
drop(rooms);
|
|
return templ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* handles requests for joining rooms and returns the real room page if token and room combination
|
|
* is correct
|
|
*/
|
|
#[get("/room?<roomname>&<token>&<player1>")]
|
|
async fn room(roomname: &str, token: usize, player1: bool) -> Template {
|
|
// lock room list mutex, don't forget to drop again
|
|
let rooms = ROOMS.lock().unwrap();
|
|
if rooms.contains_key(roomname) {
|
|
let room = rooms.get(roomname).unwrap();
|
|
// the room is real and the token is correct
|
|
if room.token == token {
|
|
drop(rooms);
|
|
templates::get_room(roomname, token, player1)
|
|
}
|
|
// the room is real but the token is incorrect
|
|
else {
|
|
drop(rooms);
|
|
templates::get_back_to_home("illegalroom")
|
|
}
|
|
}
|
|
// the room doesn't exist
|
|
else {
|
|
drop(rooms);
|
|
templates::get_back_to_home("illegalroom")
|
|
}
|
|
}
|
|
|
|
//*
|
|
//sends new board if there have been updates
|
|
//*
|
|
#[get("/stream/<roomname>/<token>")]
|
|
async fn stream(roomname: String, token: usize) -> EventStream![] {
|
|
let roomlist = ROOMS.lock().unwrap();
|
|
drop(roomlist);
|
|
EventStream! {
|
|
loop {
|
|
// TODO
|
|
// check if there are any new events, and then if the room token is correct
|
|
// if that's the case send the current playing board
|
|
// otherwise don't do anything
|
|
yield Event::json(&"oof".to_string());
|
|
}
|
|
}
|
|
}
|
|
|
|
//*
|
|
// adds new boards to the send queue after calculating move
|
|
//*
|
|
#[post("/play?<roomname>&<token>&<player1>&<x>&<y>")]
|
|
fn play(roomname: &str, token: usize, player1: bool, x: u8, y: u8) {
|
|
// get room mutex
|
|
let mut roomlist = ROOMS.lock().unwrap();
|
|
// check if room is legal
|
|
if rooms::room_and_token_correct(&roomlist, &roomname, &token) {
|
|
let board = &roomlist.get_mut(roomname).unwrap().board;
|
|
if board.play_is_legal(&x, &y, &player1) {
|
|
// change the board by making a new play
|
|
board.make_play(&x, &y);
|
|
let mut playlist = PLAYS.lock().unwrap();
|
|
// if the board doesn't exist yet, make a new one
|
|
if !(playlist.contains_key(roomname)) {
|
|
let rn = roomname.to_string();
|
|
playlist.insert(rn, vec![]);
|
|
}
|
|
// add new board to the play queue
|
|
playlist.get_mut(roomname).unwrap().push(board.clone());
|
|
drop(playlist);
|
|
}
|
|
}
|
|
drop(roomlist);
|
|
}
|