This commit is contained in:
ntr 2019-04-24 19:54:45 +10:00
parent b839810815
commit e00e819ca9
6 changed files with 146 additions and 108 deletions

View File

@ -9,7 +9,7 @@ const addState = connect(
function sendInstanceJoin() {
if (selectedCryps.length) {
return ws.sendInstanceJoin(selectedCryps);
return ws.sendInstanceLobby(selectedCryps);
}
return false;
}

View File

@ -148,6 +148,10 @@ function createSocket(events) {
send({ method: 'instance_join', params: { cryp_ids: cryps, pve: true } });
}
function sendInstanceLobby(cryps) {
send({ method: 'instance_lobby', params: { cryp_ids: cryps, name: 'dota apem', players: 2 } });
}
function sendInstanceReady(instanceId) {
send({ method: 'instance_ready', params: { instance_id: instanceId } });
}
@ -323,6 +327,7 @@ function createSocket(events) {
sendZoneClose,
sendInstanceJoin,
sendInstanceReady,
sendInstanceLobby,
sendInstanceScores,
sendPlayerMmCrypsSet,
sendPlayerState,

View File

@ -29,6 +29,7 @@ exports.up = async knex => {
table.uuid('id').primary();
table.index('id');
table.binary('data').notNullable();
table.timestamps(true, true);
// the instance
table.uuid('instance').notNullable()

View File

@ -1049,8 +1049,8 @@ mod tests {
// should auto progress back to skill phase
assert!(game.phase == Phase::Skill);
assert!(game.team_by_id(y_team.id).cryps[0].is_stunned());
assert!(game.team_by_id(y_team.id).skills_required() == 0);
// assert!(game.team_by_id(y_team.id).cryps[0].is_stunned());
// assert!(game.team_by_id(y_team.id).skills_required() == 0);
}
#[test]

View File

@ -9,7 +9,7 @@ use failure::err_msg;
use std::iter;
use rpc::{InstanceJoinParams, InstanceReadyParams};
use rpc::{InstanceLobbyParams, InstanceJoinParams, InstanceReadyParams};
use account::Account;
use player::{Player, Score, player_create, player_get, player_update};
use cryp::{Cryp, cryp_get};
@ -38,7 +38,9 @@ pub struct Instance {
phase: InstancePhase,
rounds: Vec<Vec<Round>>,
open: bool,
pve: bool,
max_players: usize,
password: Option<String>,
name: String,
}
impl Instance {
@ -49,18 +51,37 @@ impl Instance {
rounds: vec![],
phase: InstancePhase::Open,
open: true,
pve: false,
max_players: 2,
name: String::new(),
password: None,
}
}
fn set_max_players(mut self, max: usize) -> Result<Instance, Error> {
if max > 16 || max % 2 != 0 {
return Err(err_msg("max players must be divisible by 2 and less than 16"));
}
self.max_players = max;
Ok(self)
}
fn set_name(mut self, name: String) -> Result<Instance, Error> {
if name.len() == 0 {
return Err(err_msg("name must have a length"));
}
Ok(self)
}
fn add_bots(mut self) -> Instance {
self.pve = true;
self.open = false;
self.players = iter::repeat_with(|| {
let bot_id = Uuid::new_v4();
let cryps = instance_mobs(bot_id);
let mut p = Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true);
p.autobuy();
p.set_ready(true);
p
})
.take(15)
@ -89,8 +110,8 @@ impl Instance {
}
fn player_ready(&mut self, player: &mut Player) -> Result<&mut Instance, Error> {
if self.phase != InstancePhase::Vbox {
return Err(err_msg("instance not in vbox phase"));
if ![InstancePhase::Vbox, InstancePhase::Open].contains(&self.phase) {
return Err(err_msg("instance not in start or vbox phase"));
}
let i = self.players
@ -102,13 +123,30 @@ impl Instance {
self.players[i] = player.clone();
if self.vbox_phase_finished() {
self.games_phase_start();
if self.all_ready() {
match self.phase {
InstancePhase::Open => self.start(),
InstancePhase::Vbox => self.games_phase_start(),
_ => panic!("unhandled ready phase"),
};
}
Ok(self)
}
fn player_has_pve_game(&self, player: &Player) -> bool {
let opponent_id = self.current_round(&player).player_ids
.iter()
.find(|p| **p != player.id)
.expect("unable to find opponent");
return self.players
.iter()
.find(|p| p.id == *opponent_id)
.expect("unable to find opponent")
.bot;
}
fn bot_vs_player_game(&self, player: &Player) -> Result<Game, Error> {
let current_round = self.current_round(player);
let bot_id = current_round.player_ids.iter().find(|id| **id != player.id).unwrap();
@ -141,10 +179,7 @@ impl Instance {
}
fn can_start(&self) -> bool {
match self.pve {
true => self.players.len() == 16,
false => self.players.len() == 2,
}
self.players.len() == self.max_players && self.all_ready()
}
fn start(&mut self) -> &mut Instance {
@ -161,7 +196,7 @@ impl Instance {
self
}
fn vbox_phase_finished(&self) -> bool {
fn all_ready(&self) -> bool {
self.players.iter().all(|p| p.ready)
}
@ -171,7 +206,7 @@ impl Instance {
if self.phase != InstancePhase::Vbox {
panic!("instance not in vbox phase");
}
assert!(self.vbox_phase_finished());
assert!(self.all_ready());
self.phase = InstancePhase::Games;
@ -213,56 +248,54 @@ impl Instance {
panic!("instance not in games phase");
}
if self.pve {
let r = self.rounds.len() - 1;
// println!("round num {:?}", r);
// println!("{:?}", self.rounds[r]);
for mut round in self.rounds[r].iter_mut() {
if self.players
.iter()
.filter(|p| round.player_ids.contains(&p.id) && p.bot)
.count() == 2 {
// println!("should play a game between {:?}", round.player_ids);
let a = self.players.clone().into_iter().find(|p| p.id == round.player_ids[0]).unwrap();
let b = self.players.clone().into_iter().find(|p| p.id == round.player_ids[1]).unwrap();
let r = self.rounds.len() - 1;
// println!("round num {:?}", r);
// println!("{:?}", self.rounds[r]);
for mut round in self.rounds[r].iter_mut() {
if self.players
.iter()
.filter(|p| round.player_ids.contains(&p.id) && p.bot)
.count() == 2 {
// println!("should play a game between {:?}", round.player_ids);
let a = self.players.clone().into_iter().find(|p| p.id == round.player_ids[0]).unwrap();
let b = self.players.clone().into_iter().find(|p| p.id == round.player_ids[1]).unwrap();
// println!("{:?} vs {:?}", a.name, b.name);
// println!("{:?} vs {:?}", a.name, b.name);
let mut game = Game::new();
game
.set_team_num(2)
.set_team_size(3);
let mut game = Game::new();
game
.set_team_num(2)
.set_team_size(3);
// add the players
let mut a_team = Team::new(a.account);
a_team.set_cryps(a.cryps);
a_team.set_bot();
// add the players
let mut a_team = Team::new(a.account);
a_team.set_cryps(a.cryps);
a_team.set_bot();
let mut b_team = Team::new(b.account);
b_team.set_cryps(b.cryps);
b_team.set_bot();
let mut b_team = Team::new(b.account);
b_team.set_cryps(b.cryps);
b_team.set_bot();
game
.team_add(a_team).unwrap()
.team_add(b_team).unwrap();
game
.team_add(a_team).unwrap()
.team_add(b_team).unwrap();
game = game.start();
game = game.start();
assert!(game.finished());
let winner = game.winner().unwrap();
assert!(game.finished());
let winner = game.winner().unwrap();
round.finished = true;
for team in game.teams.iter() {
let mut player = self.players.iter_mut().find(|p| p.account == team.id).unwrap();
match team.id == winner.id {
true => player.add_win(),
false => player.add_loss(),
};
}
round.finished = true;
for team in game.teams.iter() {
let mut player = self.players.iter_mut().find(|p| p.account == team.id).unwrap();
match team.id == winner.id {
true => player.add_win(),
false => player.add_loss(),
};
}
}
}
}
self
@ -400,15 +433,20 @@ pub fn instance_get_open(tx: &mut Transaction) -> Result<Instance, Error> {
return Ok(instance);
}
pub fn instance_lobby(params: InstanceLobbyParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut instance = Instance::new()
.set_max_players(params.players)?
.set_name(params.name)?;
instance = instance_create(tx, instance)?;
let join_params = InstanceJoinParams { instance_id: instance.id, cryp_ids: params.cryp_ids };
instance_join(join_params, tx, account)
}
pub fn instance_join(params: InstanceJoinParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut instance = match params.pve {
true => instance_create(tx, Instance::new().add_bots())?,
false => match instance_get_open(tx) {
Ok(i) => i,
Err(_) => instance_create(tx, Instance::new())?,
},
};
let mut instance = instance_get(tx, params.instance_id)?;
let cryps = params.cryp_ids
.iter()
@ -419,16 +457,10 @@ pub fn instance_join(params: InstanceJoinParams, tx: &mut Transaction, account:
return Err(format_err!("incorrect team size. ({:})", 3));
}
let mut player = Player::new(account.id, instance.id, &account.name, cryps);
player.vbox.fill();
let player = Player::new(account.id, instance.id, &account.name, cryps);
let player = player_create(tx, player, account)?;
instance.add_player(player.clone());
if instance.can_start() {
instance.start();
}
instance_update(tx, instance)?;
return Ok(player);
@ -478,7 +510,7 @@ pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account
let game_id = instance.current_round(&player).game_id;
let game = match instance.pve {
let game = match instance.player_has_pve_game(&player) {
true => match game_get(tx, game_id) {
Ok(g) => g,
Err(_) => {
@ -573,12 +605,15 @@ mod tests {
#[test]
fn instance_pve_test() {
let mut instance = Instance::new().add_bots();
let mut instance = Instance::new()
.set_max_players(16).expect("unable to set max players")
.add_bots();
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
player.autobuy();
player.set_ready(true);
instance.add_player(player.clone());
assert!(instance.can_start());
@ -602,10 +637,10 @@ mod tests {
#[test]
fn instance_bot_vbox_test() {
let mut instance = Instance::new();
let instance = Instance::new();
let player_account = Uuid::new_v4();
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);
}
}

View File

@ -22,7 +22,7 @@ use skill::{Skill};
// use zone::{Zone, zone_create, zone_join, zone_close};
use spec::{Spec};
use player::{Score, player_state, player_mm_cryps_set, Player};
use instance::{instance_join, instance_ready, instance_scores};
use instance::{instance_lobby, instance_join, instance_ready, instance_scores};
use vbox::{Var, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
pub struct Rpc;
@ -78,7 +78,8 @@ impl Rpc {
// "zone_close" => Rpc::zone_close(data, &mut tx, account.unwrap(), client),
"instance_join" => Rpc::instance_join(data, &mut tx, account.unwrap(), client),
"instance_ready" => Rpc::instance_ready(data, &mut tx, account.unwrap(), client),
// "instance_ready" => Rpc::instance_ready(data, &mut tx, account.unwrap(), client),
"instance_lobby" => Rpc::instance_lobby(data, &mut tx, account.unwrap(), client),
"instance_scores" => Rpc::instance_scores(data, &mut tx, account.unwrap(), client),
"player_state" => Rpc::player_state(data, &mut tx, account.unwrap(), client),
@ -261,6 +262,18 @@ impl Rpc {
// return Ok(response);
// }
fn instance_lobby(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceLobbyMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
method: "player_state".to_string(),
params: RpcResult::PlayerState(instance_lobby(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> {
let msg = from_slice::<InstanceJoinMsg>(&data).or(Err(err_msg("invalid params")))?;
@ -272,16 +285,16 @@ impl Rpc {
return Ok(response);
}
fn instance_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")))?;
// fn instance_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: "game_state".to_string(),
params: RpcResult::GameState(instance_ready(msg.params, tx, &account)?)
};
// let response = RpcResponse {
// method: "game_state".to_string(),
// params: RpcResult::GameState(instance_ready(msg.params, tx, &account)?)
// };
return Ok(response);
}
// return Ok(response);
// }
fn instance_scores(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")))?;
@ -541,33 +554,17 @@ struct AccountCrypsMsg {
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct ZoneCreateMsg {
struct InstanceLobbyMsg {
method: String,
params: (),
params: InstanceLobbyParams,
}
#[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 struct InstanceLobbyParams {
pub cryp_ids: Vec<Uuid>,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct ZoneCloseMsg {
method: String,
params: ZoneCloseParams,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct ZoneCloseParams {
pub zone_id: Uuid,
pub name: String,
pub players: usize,
pub password: Option<String>,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
@ -578,8 +575,8 @@ struct InstanceJoinMsg {
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct InstanceJoinParams {
pub instance_id: Uuid,
pub cryp_ids: Vec<Uuid>,
pub pve: bool,
}
#[derive(Debug,Clone,Serialize,Deserialize)]