diff --git a/server/src/account.rs b/server/src/account.rs index 676a32fd..1d3a365d 100644 --- a/server/src/account.rs +++ b/server/src/account.rs @@ -11,6 +11,7 @@ use rpc::{AccountCreateParams, AccountLoginParams}; use cryp::{Cryp, CrypRecover, cryp_write}; use game::Game; +use zone::{Zone, zone_delete}; use failure::Error; use failure::err_msg; @@ -218,4 +219,33 @@ pub fn account_game_history(tx: &mut Transaction, account: &Account) -> Result Result { + let query = " + SELECT * + FROM zones + WHERE account = $1 + AND active = true; + "; + + let result = tx + .query(query, &[&account.id])?; + + let returned = match result.iter().next() { + Some(row) => row, + None => return Err(err_msg("no active zone")), + }; + + // tells from_slice to cast into a cryp + let bytes: Vec = returned.get("data"); + let zone = match from_slice::(&bytes) { + Ok(z) => z, + Err(_) => { + zone_delete(tx, returned.get("id"))?; + return Err(err_msg("invalid zone removed")) + }, + }; + + return Ok(zone); +} + diff --git a/server/src/game.rs b/server/src/game.rs index 6eeec5b5..fae2b833 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -77,10 +77,11 @@ pub struct Game { pub stack: Vec, pub resolved: Vec, pub log: Vec, + pub zone: Option<(Uuid, u32)>, } impl Game { - fn new() -> Game { + pub fn new() -> Game { return Game { id: Uuid::new_v4(), team_size: 0, @@ -91,29 +92,35 @@ impl Game { stack: vec![], resolved: vec![], log: vec![], + zone: None, }; } - fn set_team_num(&mut self, size: usize) -> &mut Game { + pub fn set_team_num(&mut self, size: usize) -> &mut Game { self.team_num = size; self } - fn set_team_size(&mut self, size: usize) -> &mut Game { + pub fn set_team_size(&mut self, size: usize) -> &mut Game { self.team_size = size; self } - fn set_pve(&mut self, pve: bool) -> &mut Game { + pub fn set_pve(&mut self, pve: bool) -> &mut Game { self.is_pve = pve; self } + pub fn set_zone(&mut self, id: Uuid, node: u32) -> &mut Game { + self.zone = Some((id, node)); + self + } + fn already_joined(&self, team_id: Uuid) -> bool { self.teams.iter().any(|t| t.id == team_id) } - fn team_add(&mut self, team: Team) -> Result<&mut Game, Error> { + 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")); } @@ -641,7 +648,7 @@ pub fn game_target(params: GameTargetParams, tx: &mut Transaction, account: &Acc Ok(game) } -pub fn game_new(game: &Game, tx: &mut Transaction) -> Result<(), Error> { +pub fn game_write(game: &Game, tx: &mut Transaction) -> Result<(), Error> { let game_bytes = to_vec(&game)?; let query = " @@ -754,7 +761,6 @@ fn generate_mob(lvl: u8) -> Cryp { } fn generate_mob_team(mode: PveMode, cryps: &Vec) -> Team { - let mut mob_team = Team::new(Uuid::nil()); // Default settings @@ -779,8 +785,8 @@ fn generate_mob_team(mode: PveMode, cryps: &Vec) -> Team { } -pub fn game_pve(params: GamePveParams, tx: &mut Transaction, account: &Account) -> Result { - let cryps = params.cryp_ids +pub fn game_pve_new(cryp_ids: Vec, mode: PveMode, tx: &mut Transaction, account: &Account) -> Result { + let cryps = cryp_ids .iter() .map(|id| cryp_get(tx, *id, account.id)) .collect::, Error>>()?; @@ -799,7 +805,7 @@ pub fn game_pve(params: GamePveParams, tx: &mut Transaction, account: &Account) .set_team_size(cryps.len()); // create the mob team - let mob_team = generate_mob_team(params.mode, &cryps); + let mob_team = generate_mob_team(mode, &cryps); // add the players let mut plr_team = Team::new(account.id); @@ -813,8 +819,14 @@ pub fn game_pve(params: GamePveParams, tx: &mut Transaction, account: &Account) game.start(); + return Ok(game); +} + +pub fn game_pve(params: GamePveParams, tx: &mut Transaction, account: &Account) -> Result { + let game = game_pve_new(params.cryp_ids, params.mode, tx, account)?; + // persist - game_new(&game, tx)?; + game_write(&game, tx)?; Ok(game) } @@ -841,7 +853,7 @@ pub fn game_pvp(params: GamePvpParams, tx: &mut Transaction, account: &Account) game.team_add(team)?; // persist - game_new(&game, tx)?; + game_write(&game, tx)?; players_write(account, game_id, tx)?; Ok(game) diff --git a/server/src/rpc.rs b/server/src/rpc.rs index 9c46dae9..c680005f 100644 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -17,10 +17,10 @@ use failure::err_msg; use net::Db; use cryp::{Cryp, cryp_spawn, cryp_learn, cryp_forget}; use game::{Game, PveMode, game_state, game_pve, game_pvp, game_join, game_joinable_list, game_skill, game_target}; -use account::{Account, account_create, account_login, account_from_token, account_cryps}; +use account::{Account, account_create, account_login, account_from_token, account_cryps, account_zone}; use item::{Item, items_list, item_use}; use skill::{Skill}; -use zone::{Zone, zone_create}; +use zone::{Zone, zone_create, zone_join}; pub struct Rpc; @@ -71,8 +71,10 @@ impl Rpc { "game_skill" => Rpc::game_skill(data, &mut tx, account.unwrap(), client), "game_target" => Rpc::game_target(data, &mut tx, account.unwrap(), client), "zone_create" => Rpc::zone_create(data, &mut tx, account.unwrap(), client), + "zone_join" => Rpc::zone_join(data, &mut tx, account.unwrap(), client), "account_cryps" => Rpc::account_cryps(data, &mut tx, account.unwrap(), client), "account_items" => Rpc::account_items(data, &mut tx, account.unwrap(), client), + "account_zone" => Rpc::account_zone(data, &mut tx, account.unwrap(), client), "item_use" => Rpc::item_use(data, &mut tx, account.unwrap(), client), _ => Err(format_err!("unknown method - {:?}", v.method)), @@ -298,6 +300,13 @@ impl Rpc { }) } + fn account_zone(_data: Vec, tx: &mut Transaction, account: Account, _client: &mut WebSocket) -> Result { + Ok(RpcResponse { + method: "zone_state".to_string(), + params: RpcResult::ZoneState(account_zone(tx, &account)?) + }) + } + fn item_use(data: Vec, tx: &mut Transaction, account: Account, client: &mut WebSocket) -> Result { let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; @@ -327,8 +336,16 @@ impl Rpc { return Ok(response); } + fn zone_join(data: Vec, tx: &mut Transaction, account: Account, _client: &mut WebSocket) -> Result { + let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; + let response = RpcResponse { + method: "game_state".to_string(), + params: RpcResult::GameState(zone_join(msg.params, tx, &account)?) + }; + return Ok(response); + } } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -525,11 +542,18 @@ struct ZoneCreateMsg { params: (), } -// #[derive(Debug,Clone,Serialize,Deserialize)] -// pub struct ZoneCreateParams { - -// } +#[derive(Debug,Clone,Serialize,Deserialize)] +struct ZoneJoinMsg { + method: String, + params: ZoneJoinParams, +} +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct ZoneJoinParams { + pub zone_id: Uuid, + pub node_id: u32, + pub cryp_ids: Vec, +} // #[cfg(test)] // mod tests { diff --git a/server/src/zone.rs b/server/src/zone.rs index 1aca45f1..ac37d622 100644 --- a/server/src/zone.rs +++ b/server/src/zone.rs @@ -1,6 +1,6 @@ use uuid::Uuid; use petgraph::graph::{Graph, UnGraph, NodeIndex}; -use petgraph::dot::{Dot, Config}; +// use petgraph::dot::{Dot, Config}; // Db Commons use account::Account; @@ -9,14 +9,20 @@ use postgres::transaction::Transaction; use failure::Error; use failure::err_msg; -use game::Game; +use game::{Game, PveMode, game_pve_new, game_write}; +use rpc::{ZoneJoinParams}; -pub type Zone = UnGraph; +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct Zone { + id: Uuid, + graph: UnGraph, +} + +pub type ZoneGraph = UnGraph; #[derive(Debug,Clone,PartialEq,Eq,Hash,PartialOrd,Ord,Serialize,Deserialize)] pub struct Encounter { tag: String, - id: Uuid, game_id: Option, success: bool, } @@ -25,7 +31,6 @@ impl Encounter { fn new(tag: &'static str) -> Encounter { return Encounter { tag: tag.to_string(), - id: Uuid::new_v4(), success: false, game_id: None, }; @@ -57,51 +62,61 @@ pub fn create_zone_graph() -> UnGraph { return gr; } -// pub fn zone_join(params: ZoneJoinParams, tx: &mut Transaction, account: &Account) -> Result, Error> { -// let cryps = params.cryp_ids -// .iter() -// .map(|id| cryp_get(tx, *id, account.id)) -// .collect::, Error>>()?; +pub fn zone_delete(tx: &mut Transaction, id: Uuid) -> Result<(), Error> { + let query = " + DELETE + FROM zones + WHERE id = $1; + "; -// if cryps.len() > 3 { -// return Err(err_msg("team size too large (3 max)")); -// } + let result = tx + .execute(query, &[&id])?; -// // create the game -// let mut game = Game::new(); -// // let game_id = game.id; + if result != 1 { + return Err(format_err!("unable to delete zone {:?}", id)); + } -// game -// .set_pve(true) -// .set_team_num(2) -// .set_team_size(cryps.len()); + println!("zone deleted {:?}", id); -// // create the mob team -// let mob_team = generate_mob_team(params.mode, &cryps); + return Ok(()); +} -// // add the players -// let mut plr_team = Team::new(account.id); -// plr_team -// .set_cryps(cryps); +pub fn zone_get(tx: &mut Transaction, id: Uuid) -> Result { + let query = " + SELECT * + FROM zones + WHERE id = $1 + "; + let result = tx + .query(query, &[&id])?; -// game -// .team_add(plr_team)? -// .team_add(mob_team)?; + let returned = match result.iter().next() { + Some(row) => row, + None => return Err(err_msg("zone not found")), + }; -// game.start(); - -// // persist -// game_new(&game, tx)?; - -// Ok(game) -// } - -pub fn zone_create(tx: &mut Transaction, account: &Account) -> Result, Error> { - let id = Uuid::new_v4(); - let zone = create_zone_graph(); + // tells from_slice to cast into a cryp + let bytes: Vec = returned.get("data"); + let zone = match from_slice::(&bytes) { + Ok(z) => z, + Err(_) => { + zone_delete(tx, id)?; + return Err(err_msg("invalid zone removed")) + }, + }; return Ok(zone); +} + +pub fn zone_create(tx: &mut Transaction, account: &Account) -> Result { + let id = Uuid::new_v4(); + let graph = create_zone_graph(); + + let zone = Zone { + id, + graph, + }; let bytes = to_vec(&zone)?; @@ -119,6 +134,47 @@ pub fn zone_create(tx: &mut Transaction, account: &Account) -> Result Result<(), Error> { + let bytes = to_vec(&zone)?; + + let query = " + UPDATE zones + SET data = $1 + WHERE id = $2 + RETURNING id, data; + "; + + let result = tx + .query(query, &[&bytes, &zone.id])?; + + result.iter().next().ok_or(format_err!("zone {:?} could not be written", zone))?; + + return Ok(()); +} + +pub fn zone_join(params: ZoneJoinParams, tx: &mut Transaction, account: &Account) -> Result { + let mut zone = zone_get(tx, params.zone_id)?; + + let mut game = game_pve_new(params.cryp_ids, PveMode::Normal, tx, account)?; + game.set_zone(zone.id, params.node_id); + + // borrow zone to update the encounter + { + let node_index = NodeIndex::from(params.node_id); + let encounter = zone.graph + .node_weight_mut(node_index) + .ok_or(err_msg("invalid encounter id"))?; + + encounter.game_id = Some(game.id); + } + + // persist + game_write(&game, tx)?; + zone_update(&zone, tx)?; + + return Ok(game); +} + #[cfg(test)] mod tests { use zone::*;