improve pvp queue

This commit is contained in:
ntr 2019-09-04 16:38:03 +10:00
parent a16369085c
commit b910f99f89
4 changed files with 53 additions and 34 deletions

View File

@ -4,6 +4,7 @@ use std::collections::{HashMap, HashSet};
use uuid::Uuid;
use failure::Error;
use failure::{err_msg, format_err};
use crossbeam_channel::{Sender, Receiver};
@ -28,7 +29,7 @@ type Id = usize;
pub struct PvpRequest {
pub id: Id,
pub tx: Sender<RpcMessage>,
pub account: Account,
pub account: Uuid,
}
pub struct Events {
@ -37,8 +38,6 @@ pub struct Events {
mail: Sender<Mail>,
warden: Sender<GameEvent>,
queue: Option<PvpRequest>,
clients: HashMap<Id, WsClient>,
}
@ -54,13 +53,15 @@ pub enum Event {
Push(Uuid, RpcMessage),
// client events
Queue(PvpRequest),
Queue(Id),
}
struct WsClient {
id: Id,
account: Option<Uuid>,
tx: Sender<RpcMessage>,
subs: HashSet<Uuid>,
pvp: bool,
}
impl Events {
@ -70,7 +71,6 @@ impl Events {
rx,
warden,
mail,
queue: None,
clients: HashMap::new(),
}
}
@ -110,7 +110,12 @@ impl Events {
Event::Connect(id, account, tx) => {
info!("connect id={:?} account={:?}", id, account);
let client = WsClient { id, tx, subs: HashSet::new() };
let account_id = match account {
Some(a) => Some(a.id),
None => None,
};
let client = WsClient { id, tx, account: account_id, subs: HashSet::new(), pvp: false };
self.clients.insert(id, client);
info!("clients={:?}", self.clients.len());
@ -181,30 +186,43 @@ impl Events {
Ok(())
},
Event::Queue(req) => {
info!("queue id={:?} account={:?}", req.id, req.account);
Event::Queue(id) => {
// check whether request is valid
{
let c = self.clients.get(&id)
.ok_or(format_err!("connection not found id={:?}", id))?;
self.queue = match self.queue {
Some(ref q_req) => {
info!("game queue pair found a={:?} b={:?}", req.account, q_req.account);
self.warden.send(GameEvent::Match((req, q_req.clone())))?;
None
},
None => {
info!("joined game queue id={:?} account={:?}", req.id, req.account);
match self.clients.get(&req.id) {
Some(ref c) => {
c.tx.send(RpcMessage::QueueJoined(()))?;
Some(req)
},
None => return Err(format_err!("missing client client={:?}", req.id)),
}
},
};
if let None = c.account {
return Err(err_msg("cannot join pvp queue anonymously"));
}
Ok(())
info!("pvp queue request id={:?} account={:?}", c.id, c.account);
}
// create the req for the already queued opponent
if let Some(opp_req) = match self.clients.iter_mut().find(|(_c_id, c)| c.pvp) {
Some((q_id, q)) => {
q.pvp = false;
Some(PvpRequest { id: *q_id, account: q.account.unwrap(), tx: q.tx.clone() })
},
None => None,
} {
// combine the requests and send to warden
let c = self.clients.get_mut(&id)
.ok_or(format_err!("connection not found id={:?}", id))?;
let player_req = PvpRequest { id: c.id, account: c.account.unwrap(), tx: c.tx.clone() };
self.warden.send(GameEvent::Match((opp_req, player_req)))?;
return Ok(())
}
// or flag the requester as pvp ready
let requester = self.clients.get_mut(&id).unwrap();
requester.pvp = true;
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
return Ok(());
},
}
}
}

View File

@ -691,9 +691,6 @@ pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result<Inst
Ok(instance)
}
// pub fn instance_queue(tx: &mut Transaction, a: &Account, b: &Account) -> Result<Instance, Error> {
// }
pub fn pvp(tx: &mut Transaction, a: &Account, b: &Account) -> Result<Instance, Error> {
let mut instance = Instance::new()
// TODO generate nice game names

View File

@ -19,7 +19,7 @@ use ws::{listen, CloseCode, Message, Handler, Request, Response};
use account::{Account};
use account;
use construct::{Construct};
use events::{Event, PvpRequest};
use events::{Event};
use game::{Game, game_state, game_skill, game_ready};
use instance::{Instance, instance_state, instance_practice, instance_ready};
use item::{Item, ItemInfoCtr, item_info};
@ -132,8 +132,7 @@ impl Connection {
// evented but authorization required
match v {
RpcRequest::InstanceQueue {} => {
let pvp = PvpRequest { id: self.id, account: account.clone(), tx: self.ws.clone() };
self.events.send(Event::Queue(pvp))?;
self.events.send(Event::Queue(self.id))?;
return Ok(RpcMessage::QueueRequested(()));
},
_ => (),

View File

@ -8,6 +8,7 @@ use crossbeam_channel::{tick, Sender, Receiver};
use postgres::transaction::Transaction;
use failure::Error;
use account;
use game::{games_need_upkeep, game_update, game_write, game_delete};
use instance;
use instance::{instances_need_upkeep, instances_idle, instance_update, instance_delete};
@ -91,7 +92,11 @@ impl Warden {
let db = self.pool.get()?;
let mut tx = db.transaction()?;
let instance = instance::pvp(&mut tx, &pair.0.account, &pair.1.account)?;
let a = account::select(&db, pair.0.account)?;
let b = account::select(&db, pair.1.account)?;
let instance = instance::pvp(&mut tx, &a, &b)?;
tx.commit()?;
// subscribe users to instance events