This commit is contained in:
ntr 2019-04-25 12:02:10 +10:00
parent e00e819ca9
commit 8e012cd5ea
8 changed files with 203 additions and 135 deletions

View File

@ -237,8 +237,15 @@ function createSocket(events) {
player_state: playerState, player_state: playerState,
}; };
function logout() {
localStorage.removeItem('account');
account = null;
event.setAccount(null);
}
function errHandler(error) { function errHandler(error) {
switch (error) { switch (error) {
case 'invalid token': return logout();
case 'no active zone': return sendZoneCreate(); case 'no active zone': return sendZoneCreate();
case 'no cryps selected': return events.errorPrompt('select_cryps'); case 'no cryps selected': return events.errorPrompt('select_cryps');
case 'node requirements not met': return events.errorPrompt('complete_nodes'); case 'node requirements not met': return events.errorPrompt('complete_nodes');

View File

@ -16,15 +16,10 @@ exports.up = async knex => {
table.binary('data').notNullable(); table.binary('data').notNullable();
table.boolean('open') table.boolean('open')
.defaultTo(true) .defaultTo(true)
.notNullable(); .notNullable()
.index();
}); });
await knex.schema.raw(
// eslint-disable-next-line max-len
'CREATE UNIQUE INDEX instances_open ON instances (open) WHERE open = true;'
);
await knex.schema.createTable('players', table => { await knex.schema.createTable('players', table => {
table.uuid('id').primary(); table.uuid('id').primary();
table.index('id'); table.index('id');

View File

@ -16,6 +16,15 @@
# WORK WORK # WORK WORK
## NOW ## NOW
*INSTANCES*
lobby opens
add player
add player
players ready
on start -> vbox
*CLIENT* *CLIENT*
* general * general
* icons change with % * icons change with %

View File

@ -12,7 +12,7 @@ use rpc::{GameStateParams, GameSkillParams};
use cryp::{Cryp}; use cryp::{Cryp};
use skill::{Skill, Effect, Cast, Resolution, Event, resolve}; use skill::{Skill, Effect, Cast, Resolution, Event, resolve};
use player::{Player}; use player::{Player};
use instance::{instance_game_finished, global_game_finished}; // use instance::{instance_game_finished, global_game_finished};
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Team { pub struct Team {
@ -798,14 +798,14 @@ pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> {
result.iter().next().ok_or(format_err!("game {:?} could not be written", game))?; result.iter().next().ok_or(format_err!("game {:?} could not be written", game))?;
if game.finished() { // if game.finished() {
if let Some(i) = game.instance { // if let Some(i) = game.instance {
match i == Uuid::nil() { // match i == Uuid::nil() {
true => global_game_finished(tx, &game)?, // true => global_game_finished(tx, &game)?,
false => instance_game_finished(tx, &game, i)?, // false => instance_game_finished(tx, &game, i)?,
} // }
} // }
} // }
return Ok(()); return Ok(());
} }

View File

@ -71,6 +71,7 @@ impl Instance {
return Err(err_msg("name must have a length")); return Err(err_msg("name must have a length"));
} }
self.name = name;
Ok(self) Ok(self)
} }
@ -80,7 +81,6 @@ impl Instance {
let bot_id = Uuid::new_v4(); let bot_id = Uuid::new_v4();
let cryps = instance_mobs(bot_id); let cryps = instance_mobs(bot_id);
let mut p = Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true); let mut p = Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true);
p.autobuy();
p.set_ready(true); p.set_ready(true);
p p
}) })
@ -109,19 +109,17 @@ impl Instance {
Ok(self) Ok(self)
} }
fn player_ready(&mut self, player: &mut Player) -> Result<&mut Instance, Error> { fn player_ready(&mut self, player_id: Uuid) -> Result<&mut Instance, Error> {
if ![InstancePhase::Vbox, InstancePhase::Open].contains(&self.phase) { if ![InstancePhase::Vbox, InstancePhase::Open].contains(&self.phase) {
return Err(err_msg("instance not in start or vbox phase")); return Err(err_msg("instance not in start or vbox phase"));
} }
let i = self.players let i = self.players
.iter() .iter_mut()
.position(|p| p.id == player.id) .position(|p| p.id == player_id)
.ok_or(err_msg("player_id not found"))?; .ok_or(err_msg("player_id not found"))?;
player.set_ready(true); self.players[i].set_ready(true);
self.players[i] = player.clone();
if self.all_ready() { if self.all_ready() {
match self.phase { match self.phase {
@ -492,113 +490,130 @@ pub fn instance_scores(params: InstanceReadyParams, tx: &mut Transaction, _accou
Ok(scores) Ok(scores)
} }
pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> { pub fn instance_lobby_ready(params: InstanceReadyParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?; let 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 mut instance = instance_get(tx, params.instance_id)?;
instance.player_ready(player.id)?;
// attempting to re-ready if instance.can_start() {
// send game state instance.start();
match instance.player_ready(&mut player) { for player in instance.players.iter_mut().filter(|p| !p.bot) {
Ok(_) => (),
Err(_) => return game_get(tx, instance.current_round(&player).game_id),
};
let game_id = instance.current_round(&player).game_id;
let game = match instance.player_has_pve_game(&player) {
true => match game_get(tx, game_id) {
Ok(g) => g,
Err(_) => {
let game = instance.bot_vs_player_game(&player)?;
game_write(&game, tx)?;
game
},
},
false => match game_get(tx, game_id) {
Ok(_g) => game_instance_join(tx, player.clone(), game_id)?,
Err(_) => game_instance_new(tx, player.clone(), game_id)?,
}
};
player_update(tx, player, false)?;
instance_update(tx, instance)?;
return Ok(game);
}
pub fn global_game_finished(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
let winner = game.winner().ok_or(err_msg("game not finished"))?;
for team in game.teams.iter() {
let mut player = player_get(tx, team.id, Uuid::nil())?;
match team.id == winner.id {
true => player.add_win(),
false => player.add_loss(),
};
player.vbox.fill();
player_update(tx, player, true)?;
}
Ok(())
}
pub fn instance_game_finished(tx: &mut Transaction, game: &Game, instance_id: Uuid) -> Result<(), Error> {
// update scores
let winner = game.winner().ok_or(err_msg("game not finished"))?;
for team in game.teams.iter() {
match team.bot {
true => {
let mut instance = instance_get(tx, instance_id)?;
{
let mut player = instance.players.iter_mut().find(|p| p.account == team.id).unwrap();
match team.id == winner.id {
true => player.add_win(),
false => player.add_loss(),
};
}
instance_update(tx, instance)?;
},
false => {
let mut player = player_get(tx, team.id, instance_id)?;
match team.id == winner.id {
true => player.add_win(),
false => player.add_loss(),
};
player_update(tx, player, true)?;
},
}
}
// update instance and persist
let mut instance = instance_get(tx, instance_id)?;
instance.game_finished(game)?;
let mut instance = instance_update(tx, instance)?;
// now modify the players and write them all
// each player update will also update the instance in db
if instance.games_phase_finished() {
instance.vbox_phase_start();
let instance = instance_update(tx, instance)?;
for player in instance.players
.iter()
.filter(|p| !p.bot) {
let mut player = player_get(tx, player.account, instance_id)?;
player.vbox.fill(); player.vbox.fill();
player_update(tx, player, false)?; player_update(tx, player.clone(), false)?;
} }
} }
// println!("{:?}", instance_get(tx, instance_id)?); instance_update(tx, instance)?;
Ok(player)
Ok(())
} }
// pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
// 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)?;
// // attempting to re-ready
// // send game state
// match instance.player_ready(player.id) {
// Ok(_) => (),
// Err(_) => return game_get(tx, instance.current_round(&player).game_id),
// };
// let game_id = instance.current_round(&player).game_id;
// let game = match instance.player_has_pve_game(&player) {
// true => match game_get(tx, game_id) {
// Ok(g) => g,
// Err(_) => {
// let game = instance.bot_vs_player_game(&player)?;
// game_write(&game, tx)?;
// game
// },
// },
// false => match game_get(tx, game_id) {
// Ok(_g) => game_instance_join(tx, player.clone(), game_id)?,
// Err(_) => game_instance_new(tx, player.clone(), game_id)?,
// }
// };
// player_update(tx, player, false)?;
// instance_update(tx, instance)?;
// return Ok(game);
// }
// pub fn global_game_finished(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
// let winner = game.winner().ok_or(err_msg("game not finished"))?;
// for team in game.teams.iter() {
// let mut player = player_get(tx, team.id, Uuid::nil())?;
// match team.id == winner.id {
// true => player.add_win(),
// false => player.add_loss(),
// };
// player.vbox.fill();
// player_update(tx, player, true)?;
// }
// Ok(())
// }
// pub fn instance_game_finished(tx: &mut Transaction, game: &Game, instance_id: Uuid) -> Result<(), Error> {
// // update scores
// let winner = game.winner().ok_or(err_msg("game not finished"))?;
// for team in game.teams.iter() {
// match team.bot {
// true => {
// let mut instance = instance_get(tx, instance_id)?;
// {
// let mut player = instance.players.iter_mut().find(|p| p.account == team.id).unwrap();
// match team.id == winner.id {
// true => player.add_win(),
// false => player.add_loss(),
// };
// }
// instance_update(tx, instance)?;
// },
// false => {
// let mut player = player_get(tx, team.id, instance_id)?;
// match team.id == winner.id {
// true => player.add_win(),
// false => player.add_loss(),
// };
// player_update(tx, player, true)?;
// },
// }
// }
// // update instance and persist
// let mut instance = instance_get(tx, instance_id)?;
// instance.game_finished(game)?;
// let mut instance = instance_update(tx, instance)?;
// // now modify the players and write them all
// // each player update will also update the instance in db
// if instance.games_phase_finished() {
// instance.vbox_phase_start();
// let instance = instance_update(tx, instance)?;
// for player in instance.players
// .iter()
// .filter(|p| !p.bot) {
// let mut player = player_get(tx, player.account, instance_id)?;
// player.vbox.fill();
// player_update(tx, player, false)?;
// }
// }
// // println!("{:?}", instance_get(tx, instance_id)?);
// Ok(())
// }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -611,26 +626,27 @@ mod tests {
let player_account = Uuid::new_v4(); let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account); let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true); let player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
player.autobuy(); let player_id = player.id;
player.set_ready(true);
instance.add_player(player.clone()); instance.add_player(player);
assert!(instance.can_start());
instance.start(); assert_eq!(instance.phase, InstancePhase::Open);
instance.player_ready(player_id).unwrap();
assert_eq!(instance.phase, InstancePhase::Vbox);
assert_eq!(instance.rounds[0].len(), 8); assert_eq!(instance.rounds[0].len(), 8);
instance.player_ready(&mut player).unwrap(); instance.player_ready(player_id).unwrap();
assert!(instance.games_phase_finished()); assert!(instance.games_phase_finished());
instance.vbox_phase_start(); instance.vbox_phase_start();
instance.player_ready(&mut player).unwrap(); instance.player_ready(player_id).unwrap();
instance.vbox_phase_start(); instance.vbox_phase_start();
instance.player_ready(&mut player).unwrap(); instance.player_ready(player_id).unwrap();
assert_eq!(instance.rounds.len(), 3); assert_eq!(instance.rounds.len(), 3);
} }
@ -643,4 +659,33 @@ mod tests {
let _player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true); let _player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
} }
} #[test]
fn instance_start_test() {
let mut instance = Instance::new()
.set_max_players(2)
.expect("could not create instance");
assert_eq!(instance.max_players, 2);
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let player = Player::new(player_account, instance.id, &"a".to_string(), cryps);
let a_id = player.id;
instance.add_player(player.clone());
assert!(!instance.can_start());
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let player = Player::new(player_account, instance.id, &"b".to_string(), cryps);
let b_id = player.id;
instance.add_player(player);
instance.player_ready(a_id).expect("a ready");
assert!(!instance.can_start());
instance.player_ready(b_id).expect("b ready");
assert!(instance.can_start());
}
}

View File

@ -389,8 +389,10 @@ mod tests {
let player_account = Uuid::new_v4(); let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account); let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, Uuid::new_v4(), &"test".to_string(), cryps).set_bot(true); let mut player = Player::new(player_account, Uuid::new_v4(), &"test".to_string(), cryps).set_bot(true);
player.vbox.fill();
player.autobuy(); player.autobuy();
assert!(player.cryps.iter().all(|c| c.skills.len() == 2));
assert!(player.cryps.iter().all(|c| c.skills.len() >= 1));
} }
} }

View File

@ -22,7 +22,7 @@ use skill::{Skill};
// use zone::{Zone, zone_create, zone_join, zone_close}; // use zone::{Zone, zone_create, zone_join, zone_close};
use spec::{Spec}; use spec::{Spec};
use player::{Score, player_state, player_mm_cryps_set, Player}; use player::{Score, player_state, player_mm_cryps_set, Player};
use instance::{instance_lobby, instance_join, instance_ready, instance_scores}; use instance::{instance_lobby, instance_lobby_ready, instance_join, instance_scores};
use vbox::{Var, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip}; use vbox::{Var, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
pub struct Rpc; pub struct Rpc;
@ -273,6 +273,16 @@ impl Rpc {
return Ok(response); return Ok(response);
} }
fn instance_lobby_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceReadyMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
method: "player_state".to_string(),
params: RpcResult::PlayerState(instance_lobby_ready(msg.params, tx, &account)?)
};
return Ok(response);
}
fn instance_join(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> { fn instance_join(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceJoinMsg>(&data).or(Err(err_msg("invalid params")))?; let msg = from_slice::<InstanceJoinMsg>(&data).or(Err(err_msg("invalid params")))?;

View File

@ -421,7 +421,7 @@ impl Vbox {
bits: 18, bits: 18,
}; };
vbox.fill(); // vbox.fill();
return vbox; return vbox;
} }