game invites
This commit is contained in:
+59
-1
@@ -12,6 +12,7 @@ use account;
|
||||
use account::Account;
|
||||
use game;
|
||||
use instance;
|
||||
use names;
|
||||
|
||||
use pg::{Db, PgPool};
|
||||
use rpc::RpcMessage;
|
||||
@@ -54,6 +55,9 @@ pub enum Event {
|
||||
|
||||
// client events
|
||||
Queue(Id),
|
||||
Invite(Id),
|
||||
Join(Id, String),
|
||||
Joined(Id),
|
||||
}
|
||||
|
||||
struct WsClient {
|
||||
@@ -62,6 +66,7 @@ struct WsClient {
|
||||
tx: Sender<RpcMessage>,
|
||||
subs: HashSet<Uuid>,
|
||||
pvp: bool,
|
||||
invite: Option<String>,
|
||||
}
|
||||
|
||||
impl Events {
|
||||
@@ -115,7 +120,7 @@ impl Events {
|
||||
None => None,
|
||||
};
|
||||
|
||||
let client = WsClient { id, tx, account: account_id, subs: HashSet::new(), pvp: false };
|
||||
let client = WsClient { id, tx, account: account_id, subs: HashSet::new(), pvp: false, invite: None };
|
||||
self.clients.insert(id, client);
|
||||
|
||||
info!("clients={:?}", self.clients.len());
|
||||
@@ -223,6 +228,59 @@ impl Events {
|
||||
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
Event::Invite(id) => {
|
||||
// check whether request is valid
|
||||
let c = self.clients.get_mut(&id)
|
||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||
|
||||
if let None = c.account {
|
||||
return Err(err_msg("cannot join pvp queue anonymously"));
|
||||
}
|
||||
|
||||
let code = names::name().split_whitespace().collect::<Vec<&str>>().join("-");
|
||||
info!("pvp invite request id={:?} account={:?} code={:?}", c.id, c.account, code);
|
||||
c.invite = Some(code.clone());
|
||||
c.tx.send(RpcMessage::Invite(code))?;
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
Event::Join(id, code) => {
|
||||
// check whether request is valid
|
||||
let c = self.clients.get(&id)
|
||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||
|
||||
if let None = c.account {
|
||||
return Err(err_msg("cannot join pvp queue anonymously"));
|
||||
}
|
||||
|
||||
info!("pvp join request id={:?} account={:?} code={:?}", c.id, c.account, code);
|
||||
|
||||
let inv = self.clients.iter()
|
||||
.filter(|(_id, c)| c.invite.is_some())
|
||||
.find(|(_id, c)| match c.invite {
|
||||
Some(ref c) => *c == code,
|
||||
None => false,
|
||||
})
|
||||
.map(|(_id, c)| PvpRequest { id: c.id, account: c.account.unwrap(), tx: c.tx.clone() })
|
||||
.ok_or(format_err!("invite not found code={:?}", code))?;
|
||||
|
||||
let join = PvpRequest { id: c.id, account: c.account.unwrap(), tx: c.tx.clone() };
|
||||
|
||||
self.warden.send(GameEvent::Match((join, inv)))?;
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
Event::Joined(id) => {
|
||||
// check whether request is valid
|
||||
let c = self.clients.get_mut(&id)
|
||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||
|
||||
c.pvp = false;
|
||||
c.invite = None;
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+82
-67
@@ -62,6 +62,10 @@ pub enum RpcMessage {
|
||||
QueueJoined(()),
|
||||
QueueCancelled(()),
|
||||
|
||||
InviteRequested(()),
|
||||
Invite(String),
|
||||
Joining(()),
|
||||
|
||||
Error(String),
|
||||
}
|
||||
|
||||
@@ -91,6 +95,8 @@ pub enum RpcRequest {
|
||||
SubscriptionState {},
|
||||
EmailState {},
|
||||
|
||||
InstanceInvite {},
|
||||
InstanceJoin { code: String },
|
||||
InstanceQueue {},
|
||||
InstancePractice {},
|
||||
InstanceAbandon { instance_id: Uuid },
|
||||
@@ -136,99 +142,108 @@ impl Connection {
|
||||
None => return Err(err_msg("auth required")),
|
||||
};
|
||||
|
||||
// evented but authorization required
|
||||
match v {
|
||||
RpcRequest::InstanceQueue {} => {
|
||||
self.events.send(Event::Queue(self.id))?;
|
||||
return Ok(RpcMessage::QueueRequested(()));
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// all good, let's make a tx and process
|
||||
let mut tx = db.transaction()?;
|
||||
|
||||
let request = v.clone();
|
||||
|
||||
let response = match v {
|
||||
RpcRequest::AccountState {} =>
|
||||
Ok(RpcMessage::AccountState(account.clone())),
|
||||
RpcRequest::AccountConstructs {} =>
|
||||
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &account)?)),
|
||||
RpcRequest::AccountInstances {} =>
|
||||
Ok(RpcMessage::AccountInstances(account::account_instances(&mut tx, account)?)),
|
||||
RpcRequest::AccountSetTeam { ids } =>
|
||||
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &account, ids)?)),
|
||||
// evented but authorization required
|
||||
RpcRequest::InstanceQueue {} => {
|
||||
self.events.send(Event::Queue(self.id))?;
|
||||
Ok(RpcMessage::QueueRequested(()))
|
||||
},
|
||||
RpcRequest::InstanceInvite {} => {
|
||||
self.events.send(Event::Invite(self.id))?;
|
||||
Ok(RpcMessage::InviteRequested(()))
|
||||
},
|
||||
RpcRequest::InstanceJoin { code } => {
|
||||
self.events.send(Event::Join(self.id, code))?;
|
||||
Ok(RpcMessage::Joining(()))
|
||||
},
|
||||
_ => {
|
||||
// all good, let's make a tx and process
|
||||
let mut tx = db.transaction()?;
|
||||
|
||||
RpcRequest::EmailState {} =>
|
||||
Ok(RpcMessage::EmailState(mail::select_account(&db, account.id)?)),
|
||||
let res = match v {
|
||||
RpcRequest::AccountState {} =>
|
||||
Ok(RpcMessage::AccountState(account.clone())),
|
||||
RpcRequest::AccountConstructs {} =>
|
||||
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &account)?)),
|
||||
RpcRequest::AccountInstances {} =>
|
||||
Ok(RpcMessage::AccountInstances(account::account_instances(&mut tx, account)?)),
|
||||
RpcRequest::AccountSetTeam { ids } =>
|
||||
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &account, ids)?)),
|
||||
|
||||
RpcRequest::SubscriptionState {} =>
|
||||
Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, &self.stripe, &account)?)),
|
||||
RpcRequest::EmailState {} =>
|
||||
Ok(RpcMessage::EmailState(mail::select_account(&db, account.id)?)),
|
||||
|
||||
// RpcRequest::AccountShop {} =>
|
||||
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
||||
RpcRequest::SubscriptionState {} =>
|
||||
Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, &self.stripe, &account)?)),
|
||||
|
||||
// RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account),
|
||||
// RpcRequest::AccountShop {} =>
|
||||
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
||||
|
||||
RpcRequest::GameState { id } =>
|
||||
Ok(RpcMessage::GameState(game_state(&mut tx, account, id)?)),
|
||||
// RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account),
|
||||
|
||||
RpcRequest::GameSkill { game_id, construct_id, target_construct_id, skill } =>
|
||||
Ok(RpcMessage::GameState(game_skill(&mut tx, account, game_id, construct_id, target_construct_id, skill)?)),
|
||||
RpcRequest::GameState { id } =>
|
||||
Ok(RpcMessage::GameState(game_state(&mut tx, account, id)?)),
|
||||
|
||||
RpcRequest::GameSkillClear { game_id } =>
|
||||
Ok(RpcMessage::GameState(game_skill_clear(&mut tx, account, game_id)?)),
|
||||
RpcRequest::GameSkill { game_id, construct_id, target_construct_id, skill } =>
|
||||
Ok(RpcMessage::GameState(game_skill(&mut tx, account, game_id, construct_id, target_construct_id, skill)?)),
|
||||
|
||||
RpcRequest::GameReady { id } =>
|
||||
Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)),
|
||||
RpcRequest::GameSkillClear { game_id } =>
|
||||
Ok(RpcMessage::GameState(game_skill_clear(&mut tx, account, game_id)?)),
|
||||
|
||||
RpcRequest::InstancePractice {} =>
|
||||
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, account)?)),
|
||||
RpcRequest::GameReady { id } =>
|
||||
Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)),
|
||||
|
||||
// these two can return GameState or InstanceState
|
||||
RpcRequest::InstanceReady { instance_id } =>
|
||||
Ok(instance_ready(&mut tx, account, instance_id)?),
|
||||
RpcRequest::InstanceState { instance_id } =>
|
||||
Ok(instance_state(&mut tx, instance_id)?),
|
||||
RpcRequest::InstanceAbandon { instance_id } =>
|
||||
Ok(instance_abandon(&mut tx, account, instance_id)?),
|
||||
RpcRequest::InstancePractice {} =>
|
||||
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, account)?)),
|
||||
|
||||
RpcRequest::VboxAccept { instance_id, group, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_accept(&mut tx, account, instance_id, group, index)?)),
|
||||
// these two can return GameState or InstanceState
|
||||
RpcRequest::InstanceReady { instance_id } =>
|
||||
Ok(instance_ready(&mut tx, account, instance_id)?),
|
||||
RpcRequest::InstanceState { instance_id } =>
|
||||
Ok(instance_state(&mut tx, instance_id)?),
|
||||
RpcRequest::InstanceAbandon { instance_id } =>
|
||||
Ok(instance_abandon(&mut tx, account, instance_id)?),
|
||||
|
||||
RpcRequest::VboxApply { instance_id, construct_id, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, account, instance_id, construct_id, index)?)),
|
||||
RpcRequest::VboxAccept { instance_id, group, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_accept(&mut tx, account, instance_id, group, index)?)),
|
||||
|
||||
RpcRequest::VboxCombine { instance_id, indices } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, account, instance_id, indices)?)),
|
||||
RpcRequest::VboxApply { instance_id, construct_id, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, account, instance_id, construct_id, index)?)),
|
||||
|
||||
RpcRequest::VboxDiscard { instance_id } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_discard(&mut tx, account, instance_id)?)),
|
||||
RpcRequest::VboxCombine { instance_id, indices } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, account, instance_id, indices)?)),
|
||||
|
||||
RpcRequest::VboxReclaim { instance_id, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_reclaim(&mut tx, account, instance_id, index)?)),
|
||||
RpcRequest::VboxDiscard { instance_id } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_discard(&mut tx, account, instance_id)?)),
|
||||
|
||||
RpcRequest::VboxUnequip { instance_id, construct_id, target } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, account, instance_id, construct_id, target)?)),
|
||||
RpcRequest::VboxReclaim { instance_id, index } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_reclaim(&mut tx, account, instance_id, index)?)),
|
||||
|
||||
RpcRequest::MtxConstructSpawn {} =>
|
||||
Ok(RpcMessage::ConstructSpawn(mtx::new_construct(&mut tx, account)?)),
|
||||
RpcRequest::VboxUnequip { instance_id, construct_id, target } =>
|
||||
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, account, instance_id, construct_id, target)?)),
|
||||
|
||||
RpcRequest::MtxConstructApply { mtx, construct_id, name } =>
|
||||
Ok(RpcMessage::AccountTeam(mtx::apply(&mut tx, account, mtx, construct_id, name)?)),
|
||||
RpcRequest::MtxConstructSpawn {} =>
|
||||
Ok(RpcMessage::ConstructSpawn(mtx::new_construct(&mut tx, account)?)),
|
||||
|
||||
RpcRequest::MtxBuy { mtx } =>
|
||||
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
||||
RpcRequest::MtxConstructApply { mtx, construct_id, name } =>
|
||||
Ok(RpcMessage::AccountTeam(mtx::apply(&mut tx, account, mtx, construct_id, name)?)),
|
||||
|
||||
RpcRequest::SubscriptionEnding { ending } =>
|
||||
Ok(RpcMessage::SubscriptionState(payments::subscription_ending(&mut tx, &self.stripe, account, ending)?)),
|
||||
RpcRequest::MtxBuy { mtx } =>
|
||||
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
||||
|
||||
_ => Err(format_err!("unknown request request={:?}", request)),
|
||||
RpcRequest::SubscriptionEnding { ending } =>
|
||||
Ok(RpcMessage::SubscriptionState(payments::subscription_ending(&mut tx, &self.stripe, account, ending)?)),
|
||||
|
||||
_ => Err(format_err!("unknown request request={:?}", request)),
|
||||
};
|
||||
|
||||
tx.commit()?;
|
||||
res
|
||||
}
|
||||
};
|
||||
|
||||
tx.commit()?;
|
||||
|
||||
info!("request={:?} account={:?} duration={:?}", request, account.name, begin.elapsed());
|
||||
|
||||
return response;
|
||||
|
||||
@@ -90,6 +90,10 @@ impl Warden {
|
||||
fn on_match(&mut self, pair: Pair) -> Result<(), Error> {
|
||||
info!("received pair={:?}", pair);
|
||||
|
||||
// clear pvp status
|
||||
self.events.send(Event::Joined(pair.0.id))?;
|
||||
self.events.send(Event::Joined(pair.1.id))?;
|
||||
|
||||
let db = self.pool.get()?;
|
||||
let mut tx = db.transaction()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user