MVP BOY
This commit is contained in:
parent
b650f8d95a
commit
70aabd39e9
9 changed files with 150 additions and 123 deletions
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
target/
|
||||
Cargo.lock
|
||||
games/
|
||||
|
|
|
@ -23,10 +23,8 @@ extern crate ini;
|
|||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::{env, time};
|
||||
|
||||
use mozaic::modules::types::*;
|
||||
use mozaic::modules::{game, StepLock};
|
||||
use mozaic::modules::{game};
|
||||
|
||||
use futures::executor::ThreadPool;
|
||||
use futures::future::FutureExt;
|
||||
|
@ -66,7 +64,20 @@ fn get_colour(value: Value, _: HashMap<String, Value>) -> tera::Result<Value> {
|
|||
return Ok(Value::String(COLOURS[value.as_u64().unwrap_or(0) as usize].to_string()));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
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::new().unwrap();
|
||||
pool.spawn_ok(fut.map(|_| ()));
|
||||
let gm = create_game_manager("0.0.0.0:9142", pool.clone());
|
||||
|
||||
|
||||
let mut routes = Vec::new();
|
||||
routes::fuel(&mut routes);
|
||||
|
||||
|
@ -75,106 +86,22 @@ fn main() {
|
|||
engines.tera.register_filter("get_colour", get_colour);
|
||||
});
|
||||
|
||||
|
||||
rocket::ignite()
|
||||
.manage(gm)
|
||||
.manage(pool)
|
||||
.attach(tera)
|
||||
.mount("/", routes)
|
||||
.launch()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// // Load the config and start the game.
|
||||
// #[async_std::main]
|
||||
// async fn main() {
|
||||
// let args: Vec<String> = env::args().collect();
|
||||
// let name = args[0].clone();
|
||||
// match run(args).await {
|
||||
// None => print_info(&name),
|
||||
// _ => {}
|
||||
// };
|
||||
// }
|
||||
|
||||
fn build_builder(
|
||||
pool: ThreadPool,
|
||||
number_of_clients: u64,
|
||||
max_turns: u64,
|
||||
map: &str,
|
||||
location: &str,
|
||||
) -> game::Builder<planetwars::PlanetWarsGame> {
|
||||
let config = planetwars::Config {
|
||||
map_file: map.to_string(),
|
||||
max_turns: max_turns,
|
||||
};
|
||||
|
||||
let game =
|
||||
planetwars::PlanetWarsGame::new(config.create_game(number_of_clients as usize), location);
|
||||
|
||||
let players: Vec<PlayerId> = (0..number_of_clients).collect();
|
||||
|
||||
game::Builder::new(players.clone(), game).with_step_lock(
|
||||
StepLock::new(players.clone(), pool.clone())
|
||||
.with_timeout(std::time::Duration::from_secs(1)),
|
||||
)
|
||||
}
|
||||
|
||||
async fn run(args: Vec<String>) -> Option<()> {
|
||||
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 addr = "127.0.0.1:9142".parse::<SocketAddr>().unwrap();
|
||||
|
||||
let map = args.get(1)?;
|
||||
let number_of_clients = args
|
||||
.get(2)
|
||||
.map(|x| x.parse().expect("Client number should be a number"))
|
||||
.unwrap_or(1);
|
||||
let location = args.get(3).map(|x| x.as_str()).unwrap_or("game.json");
|
||||
let max_turns: u64 = args
|
||||
.get(4)
|
||||
.map(|x| x.parse().expect("Max turns should be a number"))
|
||||
.unwrap_or(500);
|
||||
|
||||
let pool = ThreadPool::new().ok()?;
|
||||
pool.spawn_ok(fut.map(|_| ()));
|
||||
|
||||
fn create_game_manager(tcp: &str, pool: ThreadPool) -> game::Manager {
|
||||
let addr = tcp.parse::<SocketAddr>().unwrap();
|
||||
let (gmb, handle) = game::Manager::builder(pool.clone());
|
||||
pool.spawn_ok(handle.map(|_| ()));
|
||||
let ep = TcpEndpoint::new(addr, pool.clone());
|
||||
|
||||
let gmb = gmb.add_endpoint(ep, "TCP endpoint");
|
||||
let mut gm = gmb.build();
|
||||
|
||||
let game_builder = build_builder(pool.clone(), number_of_clients, max_turns, map, location);
|
||||
std::thread::sleep(time::Duration::from_millis(3000));
|
||||
|
||||
let mut current_game = gm.start_game(game_builder).await.unwrap();
|
||||
|
||||
// loop {
|
||||
// match gm.get_state(current_game).await {
|
||||
// None => {
|
||||
// println!("Game finished, let's play a new one");
|
||||
// let game_builder =
|
||||
// build_builder(pool.clone(), number_of_clients, max_turns, map, location);
|
||||
// current_game = gm.start_game(game_builder).await.unwrap();
|
||||
// }
|
||||
// Some(state) => {
|
||||
// println!("{:?}", state);
|
||||
// }
|
||||
// }
|
||||
// std::thread::sleep(time::Duration::from_millis(3000));
|
||||
// }
|
||||
|
||||
handle.await;
|
||||
|
||||
std::thread::sleep(time::Duration::from_millis(100));
|
||||
|
||||
Some(())
|
||||
gmb.build()
|
||||
}
|
||||
|
||||
// fn print_info(name: &str) {
|
||||
// println!(
|
||||
// "Usage: {} map_location [number_of_clients [output [max_turns]]]",
|
||||
// name
|
||||
// );
|
||||
// }
|
||||
|
|
|
@ -19,22 +19,28 @@ use pw_rules::Dispatch;
|
|||
pub struct PlanetWarsGame {
|
||||
state: pw_rules::PlanetWars,
|
||||
planet_map: HashMap<String, usize>,
|
||||
log_file_loc: String,
|
||||
log_file: File,
|
||||
turns: u64,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl PlanetWarsGame {
|
||||
pub fn new(state: pw_rules::PlanetWars, location: &str) -> Self {
|
||||
pub fn new(state: pw_rules::PlanetWars, location: &str, name: &str) -> Self {
|
||||
let planet_map = state
|
||||
.planets
|
||||
.iter()
|
||||
.map(|p| (p.name.clone(), p.id))
|
||||
.collect();
|
||||
let file = File::create(location).unwrap();
|
||||
let file = File::create(format!("static/games/{}", location)).unwrap();
|
||||
|
||||
Self {
|
||||
state,
|
||||
planet_map,
|
||||
log_file_loc: location.to_string(),
|
||||
log_file: file,
|
||||
turns: 0,
|
||||
name: name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,6 +165,8 @@ impl PlanetWarsGame {
|
|||
}
|
||||
}
|
||||
|
||||
use std::fs::OpenOptions;
|
||||
use ini::Ini;
|
||||
impl game::Controller for PlanetWarsGame {
|
||||
fn start(&mut self) -> Vec<HostMsg> {
|
||||
let mut updates = Vec::new();
|
||||
|
@ -167,6 +175,8 @@ impl game::Controller for PlanetWarsGame {
|
|||
}
|
||||
|
||||
fn step(&mut self, turns: Vec<PlayerMsg>) -> Vec<HostMsg> {
|
||||
self.turns += 1;
|
||||
|
||||
let mut updates = Vec::new();
|
||||
|
||||
let alive = self.state.living_players();
|
||||
|
@ -181,6 +191,20 @@ impl game::Controller for PlanetWarsGame {
|
|||
}
|
||||
|
||||
fn is_done(&mut self) -> bool {
|
||||
self.state.is_finished()
|
||||
if self.state.is_finished() {
|
||||
|
||||
let mut f = match OpenOptions::new().append(true).open("games.ini") { Err(_) => return true, Ok(f) => f };
|
||||
|
||||
let mut conf = Ini::new();
|
||||
conf.with_section(Some(self.log_file_loc.clone()))
|
||||
.set("name", &self.name)
|
||||
.set("turns", format!("{}", self.turns));
|
||||
|
||||
conf.write_to(&mut f).unwrap();
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
use serde::{Deserialize};
|
||||
|
||||
use rocket::Route;
|
||||
use rocket::{Route, State};
|
||||
use rocket::response::NamedFile;
|
||||
|
||||
use rocket_contrib::templates::Template;
|
||||
|
@ -80,6 +80,58 @@ async fn map_get(file: String) -> Result<Template, String> {
|
|||
Ok(Template::render("map_partial", &serde_json::from_str::<serde_json::Value>(&content).unwrap()))
|
||||
}
|
||||
|
||||
pub fn fuel(routes: &mut Vec<Route>) {
|
||||
routes.extend(routes![files, index, map_post, map_get, maps_get, builder_get, visualizer_get]);
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct GameReq {
|
||||
nop: u64,
|
||||
max_turns: u64,
|
||||
map: String,
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[post("/lobby", data="<game_req>")]
|
||||
async fn game_post(game_req: Json<GameReq>, tp: State<'_, ThreadPool>, gm: State<'_, game::Manager>) -> Result<String, String> {
|
||||
let game = build_builder(tp.clone(), game_req.nop, game_req.max_turns, &game_req.map, &game_req.name);
|
||||
let game_id = gm.start_game(game).await;
|
||||
Ok(format!("{:?}", gm.get_state(game_id.unwrap()).await))
|
||||
}
|
||||
|
||||
pub fn fuel(routes: &mut Vec<Route>) {
|
||||
routes.extend(routes![files, index, map_post, map_get, maps_get, builder_get, visualizer_get, game_post]);
|
||||
}
|
||||
|
||||
|
||||
use crate::planetwars;
|
||||
use mozaic::modules::types::*;
|
||||
use mozaic::modules::{game, StepLock};
|
||||
use futures::executor::ThreadPool;
|
||||
|
||||
use rand::prelude::*;
|
||||
fn generate_string_id() -> String {
|
||||
rand::thread_rng()
|
||||
.sample_iter(&rand::distributions::Alphanumeric)
|
||||
.take(15)
|
||||
.collect::<String>() + ".json"
|
||||
}
|
||||
|
||||
fn build_builder(
|
||||
pool: ThreadPool,
|
||||
number_of_clients: u64,
|
||||
max_turns: u64,
|
||||
map: &str,
|
||||
name: &str,
|
||||
) -> game::Builder<planetwars::PlanetWarsGame> {
|
||||
let config = planetwars::Config {
|
||||
map_file: map.to_string(),
|
||||
max_turns: max_turns,
|
||||
};
|
||||
|
||||
let game =
|
||||
planetwars::PlanetWarsGame::new(config.create_game(number_of_clients as usize), &generate_string_id(), name);
|
||||
|
||||
let players: Vec<PlayerId> = (0..number_of_clients).collect();
|
||||
|
||||
game::Builder::new(players.clone(), game).with_step_lock(
|
||||
StepLock::new(players.clone(), pool.clone())
|
||||
.with_timeout(std::time::Duration::from_secs(1)),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ const ids = {};
|
|||
["map_holder", "name", "turns", "nop"].forEach(id => ids[id] = document.getElementById(id));
|
||||
|
||||
var last_map;
|
||||
var last_url;
|
||||
|
||||
async function handle_map_click(url, event) {
|
||||
if (last_map) {
|
||||
|
@ -9,10 +10,30 @@ async function handle_map_click(url, event) {
|
|||
}
|
||||
last_map = event.target;
|
||||
event.target.classList.add("selected");
|
||||
last_url = url;
|
||||
const c = await fetch(url);
|
||||
ids["map_holder"].innerHTML = await c.text();
|
||||
}
|
||||
|
||||
async function start_game() {
|
||||
const obj = {
|
||||
"nop": parseInt(ids["nop"].value),
|
||||
"name": ids["name"].value,
|
||||
"map": last_url,
|
||||
"max_turns": parseInt(ids["turns"].value),
|
||||
};
|
||||
|
||||
console.log(obj);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onreadystatechange = async function() {
|
||||
console.log(this);
|
||||
console.log(await this.text());
|
||||
|
||||
// TODO: make response visible
|
||||
};
|
||||
|
||||
xhr.open("POST", "/lobby");
|
||||
xhr.send(JSON.stringify(obj));
|
||||
}
|
|
@ -10,7 +10,11 @@ const game_location = LOCATION + "static/games/mod.ini";
|
|||
fetch(game_location)
|
||||
.then((r) => r.text())
|
||||
.then((response) => {
|
||||
parse_ini(response);
|
||||
if (OPTIONS) {
|
||||
parse_ini(response);
|
||||
} else {
|
||||
console.log("Options is not defined, tera?");
|
||||
}
|
||||
}).catch(console.error);
|
||||
|
||||
export function handle(location, name: string) {
|
||||
|
@ -29,7 +33,8 @@ function create_option(location: string, name: string, turns: string, players: s
|
|||
const div = document.createElement("div");
|
||||
div.className = "option";
|
||||
div.onclick = (_) => handle(location, name);
|
||||
|
||||
console.log("hello there");
|
||||
console.log(`"${location}, "${name}"`);
|
||||
let ps = "";
|
||||
|
||||
if (players) {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id=options>
|
||||
<div class=".options" id=options>
|
||||
<div class="option">
|
||||
Option one
|
||||
</div>
|
||||
|
@ -88,5 +88,15 @@
|
|||
|
||||
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
|
||||
<script src="bootstrap.js"></script>
|
||||
<script>
|
||||
const URL = window.location.origin + window.location.pathname;
|
||||
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
||||
|
||||
const game_location = LOCATION + "static/games/Chandra Garrett.json";
|
||||
const name = "Chandra Garrett";
|
||||
window.setTimeout(
|
||||
() => visualizer.handle(game_location, name), 1000
|
||||
)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,15 +1,2 @@
|
|||
import { set_game_name, set_instance } from './index.ts'
|
||||
export { handle }
|
||||
from './games.ts' // IMPORT GAMES PLEASE, thank you webpack <3
|
||||
|
||||
const URL = window.location.origin + window.location.pathname;
|
||||
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
||||
|
||||
const game_location = LOCATION + "static/games/Chandra Garrett.json";
|
||||
|
||||
fetch(game_location)
|
||||
.then((r) => r.text())
|
||||
.then((response) => {
|
||||
set_instance(response);
|
||||
set_game_name("Chandra Garrett");
|
||||
}).catch(console.error);
|
||||
import { } from './index.ts'
|
||||
export { handle } from './games.ts' // IMPORT GAMES PLEASE, thank you webpack <3
|
||||
|
|
|
@ -39,7 +39,7 @@ p {
|
|||
width: 96%;
|
||||
}
|
||||
|
||||
#options {
|
||||
.options {
|
||||
background-color: #444;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
|
|
Loading…
Reference in a new issue