From 5fe394370d3e63a9bde8b4de661eb15958294eb4 Mon Sep 17 00:00:00 2001 From: ntr Date: Mon, 18 Mar 2019 16:36:26 +1100 Subject: [PATCH] global mm and startup --- ops/migrations/20181020104420_games.js | 13 +++ server/WORKLOG.md | 4 + server/src/game.rs | 111 ++++++++++++++++++++----- server/src/instance.rs | 29 ++++++- server/src/main.rs | 2 +- server/src/net.rs | 6 ++ server/src/rpc.rs | 2 +- server/src/util.rs | 21 +++++ 8 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 server/src/util.rs diff --git a/ops/migrations/20181020104420_games.js b/ops/migrations/20181020104420_games.js index a7b225e0..977e62b5 100644 --- a/ops/migrations/20181020104420_games.js +++ b/ops/migrations/20181020104420_games.js @@ -50,6 +50,19 @@ exports.up = async knex => { }); + await knex.schema.createTable('matchmaking', async table => { + table.uuid('id').primary(); + table.index('id'); + table.timestamps(true, true); + + table.uuid('game').notNullable() + table.foreign('game') + .references('id') + .inTable('games') + .onDelete('NO ACTION'); + }); + + // not really sure if this is a good idea await knex('instances').insert({ id: NULL_UUID, diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 39d7124d..2d0007bb 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -13,10 +13,14 @@ combo specs fix global matchmaking +startup checks + scoreboard constants +change to ownership pattern + round system for games join instance is pve? diff --git a/server/src/game.rs b/server/src/game.rs index aa8484f2..5fe399da 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -82,7 +82,6 @@ pub struct Game { pub team_size: usize, pub team_num: usize, pub teams: Vec, - pub is_pve: bool, pub phase: Phase, pub stack: Vec, pub resolved: Vec, @@ -98,7 +97,6 @@ impl Game { team_size: 0, team_num: 0, teams: vec![], - is_pve: true, phase: Phase::Start, stack: vec![], resolved: vec![], @@ -118,11 +116,6 @@ impl Game { self } - pub fn set_pve(&mut self, pve: bool) -> &mut Game { - self.is_pve = pve; - self - } - pub fn set_instance(&mut self, id: Uuid) -> &mut Game { self.instance = Some(id); self @@ -133,6 +126,10 @@ impl Game { self } + pub fn joinable(&self) -> bool { + self.can_start() + } + pub fn team_add(&mut self, team: Team) -> Result<&mut Game, Error> { if self.teams.len() == self.team_num { return Err(err_msg("maximum number of teams")); @@ -142,6 +139,10 @@ impl Game { return Err(err_msg("team already in game")); } + if team.cryps.iter().all(|c| c.skills.len() == 0) { + return Err(err_msg("your cryps have no skills")); + } + let team_description = team.cryps.iter().map(|c| c.name.clone()).collect::>().join(", "); self.log.push(format!("{:} has joined the game.", team_description)); @@ -211,11 +212,9 @@ impl Game { self.stack.clear(); - if self.is_pve { - self.pve_add_skills(); - if self.skill_phase_finished() { - self.resolve_phase_start(); - } + self.pve_add_skills(); + if self.skill_phase_finished() { + self.resolve_phase_start(); } self @@ -261,7 +260,6 @@ impl Game { }; } } - self } @@ -651,6 +649,81 @@ pub fn game_get(tx: &mut Transaction, id: Uuid) -> Result { return Ok(game); } +pub fn game_global_startup(tx: &mut Transaction) -> Result<(), Error> { + if game_global_get(tx).is_ok() { + println!("global mm game exists"); + return Ok(()); + } + + let mut game = Game::new(); + + game + .set_team_num(2) + .set_team_size(3) + .set_mode(GameMode::Pvp); + + game_write(&game, tx)?; + + let query = " + INSERT INTO matchmaking (id, game) + VALUES ($1, $2) + RETURNING id; + "; + + let result = tx + .query(query, &[&Uuid::nil(), &game.id])?; + + result.iter().next().ok_or(format_err!("no game written"))?; + + println!("{:} wrote global mm startup", game.id); + + return Ok(()); +} + +pub fn game_global_set(tx: &mut Transaction, game: &Game) -> Result<(), Error> { + let query = " + UPDATE matchmaking + SET game = $1 + WHERE id = $2 + RETURNING id, game; + "; + + let result = tx + .query(query, &[&game.id, &Uuid::nil()])?; + + result.iter() + .next() + .ok_or(err_msg("could not set global game mm"))?; + + return Ok(()); +} + +pub fn game_global_get(tx: &mut Transaction) -> Result { + let query = " + SELECT * from games + WHERE id = ( + SELECT game + FROM matchmaking + WHERE id = $1 + ); + "; + + let result = tx + .query(query, &[&Uuid::nil()])?; + + let returned = match result.iter().next() { + Some(row) => row, + None => return Err(err_msg("game not found")), + }; + + // tells from_slice to cast into a cryp + let game_bytes: Vec = returned.get("data"); + let game = from_slice::(&game_bytes)?; + + return Ok(game); +} + + pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> { let game_bytes = to_vec(&game)?; @@ -693,8 +766,7 @@ pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> { // let mut game = Game::new(); // // let game_id = game.id; -// game -// .set_pve(true) +// game; // .set_team_num(2) // .set_team_size(cryps.len()) // .set_mode(mode); @@ -732,7 +804,6 @@ pub fn game_instance_new(tx: &mut Transaction, player: Player, game_id: Uuid) -> game.id = game_id; game - .set_pve(false) .set_team_num(2) .set_team_size(3) .set_instance(player.instance) @@ -761,6 +832,8 @@ pub fn game_instance_join(tx: &mut Transaction, player: Player, game_id: Uuid) - game.start(); } + println!("{:?} game joined", game.id); + game_update(&game, tx)?; Ok(game) @@ -800,8 +873,7 @@ mod tests { game .set_team_num(2) - .set_team_size(1) - .set_pve(false); + .set_team_size(1); let x_team_id = Uuid::new_v4(); let mut x_team = Team::new(x_team_id); @@ -849,8 +921,7 @@ mod tests { game .set_team_num(2) - .set_team_size(2) - .set_pve(false); + .set_team_size(2); let i_team_id = Uuid::new_v4(); let mut i_team = Team::new(i_team_id); diff --git a/server/src/instance.rs b/server/src/instance.rs index 70cc22e0..c62b616d 100644 --- a/server/src/instance.rs +++ b/server/src/instance.rs @@ -14,7 +14,7 @@ use account::Account; use player::{Player, player_create, player_get, player_update}; use cryp::{Cryp, cryp_get}; use mob::{instance_mobs}; -use game::{Game, Team, game_get, game_write, game_instance_new, game_instance_join}; +use game::{Game, Team, game_get, game_write, game_instance_new, game_instance_join, game_global_get, game_global_set}; #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] enum InstancePhase { @@ -112,7 +112,6 @@ impl Instance { let mut game = Game::new(); game.id = current_round.game_id; game - .set_pve(true) .set_team_num(2) .set_team_size(3) .set_instance(self.id); @@ -219,7 +218,6 @@ impl Instance { let mut game = Game::new(); game - .set_pve(true) .set_team_num(2) .set_team_size(3); @@ -416,9 +414,34 @@ pub fn instance_join(params: InstanceJoinParams, tx: &mut Transaction, account: return Ok(player); } +pub fn instance_ready_global(tx: &mut Transaction, _account: &Account, player: Player) -> Result { + // get the game + let game = match game_global_get(tx) { + Ok(g) => { + println!("received global game {:?}", g.id); + // if there is one try to join + match game_instance_join(tx, player.clone(), g.id) { + Ok(g) => g, + // if fails make a new one + Err(_e) => game_instance_new(tx, player, Uuid::new_v4())?, + } + }, + // if not found make a new one + Err(_) => game_instance_new(tx, player, Uuid::new_v4())?, + }; + + // set the current game + game_global_set(tx, &game)?; + Ok(game) +} + pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account: &Account) -> Result { let mut player = player_get(tx, account.id, params.instance_id)?; + if params.instance_id == Uuid::nil() { + return instance_ready_global(tx, account, player); + } + let mut instance = instance_get(tx, params.instance_id)?; let game_id = instance.current_round(&player).game_id; diff --git a/server/src/main.rs b/server/src/main.rs index 9b43995c..89ca846c 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -30,7 +30,7 @@ mod instance; mod player; // mod zone; mod mob; - +mod util; mod vbox; use dotenv::dotenv; diff --git a/server/src/net.rs b/server/src/net.rs index 759a9cfc..862ab83d 100644 --- a/server/src/net.rs +++ b/server/src/net.rs @@ -18,6 +18,7 @@ static DB_POOL_SIZE: u32 = 20; pub type Db = PooledConnection; use rpc::{Rpc}; +use util::{startup}; // struct Server { // client: WebSocket, @@ -62,6 +63,11 @@ pub fn start() { let pool = db_connection(database_url); + { + let startup_connection = pool.get().expect("unable to get db connection"); + startup(startup_connection).unwrap(); + } + let server = TcpListener::bind("0.0.0.0:40000").unwrap(); for stream in server.incoming() { let db = pool.clone(); diff --git a/server/src/rpc.rs b/server/src/rpc.rs index 69e011c8..227807fe 100644 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -98,7 +98,7 @@ impl Rpc { }, Err(e) => { println!("{:?}", e); - Err(err_msg("invalid message")) + Err(err_msg("unknown error")) }, } } diff --git a/server/src/util.rs b/server/src/util.rs new file mode 100644 index 00000000..89a20b4a --- /dev/null +++ b/server/src/util.rs @@ -0,0 +1,21 @@ +use net::Db; +// Db Commons +use failure::Error; + +use game::{game_global_startup}; + +pub fn startup(db: Db) -> Result<(), Error> { + let mut tx = db.transaction()?; + + println!("running startup fns"); + + game_global_startup(&mut tx)?; + + match tx.commit() { + Ok(_) => { + println!("startup processes completed"); + Ok(()) + }, + Err(e) => Err(format_err!("failed to commit startup tx {:?}", e)), + } +} \ No newline at end of file