wip
This commit is contained in:
parent
1cc29f73d1
commit
445e8084e0
@ -144,8 +144,8 @@ impl Instance {
|
|||||||
.collect::<Vec<Uuid>>()
|
.collect::<Vec<Uuid>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upkeep(mut self) -> (Instance, Option<Game>) {
|
|
||||||
// time out lobbies that have been open too long
|
// time out lobbies that have been open too long
|
||||||
|
pub fn upkeep(mut self) -> (Instance, Option<Game>) {
|
||||||
if self.phase == InstancePhase::Lobby && self.phase_timed_out() {
|
if self.phase == InstancePhase::Lobby && self.phase_timed_out() {
|
||||||
self.finish();
|
self.finish();
|
||||||
return (self, None);
|
return (self, None);
|
||||||
|
|||||||
@ -31,6 +31,11 @@ pub fn bot_player() -> Player {
|
|||||||
Player::new(bot_id, None, &name(), constructs).set_bot(true)
|
Player::new(bot_id, None, &name(), constructs).set_bot(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn anon_player(id: Uuid) -> Player {
|
||||||
|
let constructs = instance_mobs(id);
|
||||||
|
Player::new(id, None, &"player".to_string(), constructs)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn anim_test_game(skill: Skill) -> Game {
|
pub fn anim_test_game(skill: Skill) -> Game {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let mut game = Game::new();
|
let mut game = Game::new();
|
||||||
|
|||||||
@ -44,6 +44,16 @@ impl Account {
|
|||||||
|
|
||||||
Ok(Player::new(self.id, Some(self.img), &self.name, constructs))
|
Ok(Player::new(self.id, Some(self.img), &self.name, constructs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn anonymous() -> Account {
|
||||||
|
Account {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
img: Uuid::new_v4(),
|
||||||
|
name: "you".to_string(),
|
||||||
|
balance: 0,
|
||||||
|
subscribed: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TryFrom<postgres::rows::Row<'a>> for Account {
|
impl<'a> TryFrom<postgres::rows::Row<'a>> for Account {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ use warden::{GameEvent};
|
|||||||
use mail::Mail;
|
use mail::Mail;
|
||||||
|
|
||||||
pub type EventsTx = Sender<Event>;
|
pub type EventsTx = Sender<Event>;
|
||||||
type Id = usize;
|
type Id = Uuid;
|
||||||
|
|
||||||
// this is pretty heavyweight
|
// this is pretty heavyweight
|
||||||
// but it makes the ergonomics easy
|
// but it makes the ergonomics easy
|
||||||
@ -43,7 +43,7 @@ pub struct Events {
|
|||||||
#[derive(Debug,Clone)]
|
#[derive(Debug,Clone)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
// ws lifecycle
|
// ws lifecycle
|
||||||
Connect(Id, Option<Account>, Sender<RpcMessage>),
|
Connect(Id, Account, Sender<RpcMessage>),
|
||||||
Disconnect(Id),
|
Disconnect(Id),
|
||||||
Subscribe(Id, Uuid),
|
Subscribe(Id, Uuid),
|
||||||
Unsubscribe(Id, Uuid),
|
Unsubscribe(Id, Uuid),
|
||||||
@ -64,7 +64,6 @@ pub enum Event {
|
|||||||
|
|
||||||
struct WsClient {
|
struct WsClient {
|
||||||
id: Id,
|
id: Id,
|
||||||
account: Option<Uuid>,
|
|
||||||
tx: Sender<RpcMessage>,
|
tx: Sender<RpcMessage>,
|
||||||
subs: HashSet<Uuid>,
|
subs: HashSet<Uuid>,
|
||||||
chat: Option<(Uuid, String)>,
|
chat: Option<(Uuid, String)>,
|
||||||
@ -118,14 +117,8 @@ impl Events {
|
|||||||
Event::Connect(id, account, tx) => {
|
Event::Connect(id, account, tx) => {
|
||||||
info!("connect id={:?} account={:?}", id, account);
|
info!("connect id={:?} account={:?}", id, account);
|
||||||
|
|
||||||
let account_id = match account {
|
|
||||||
Some(a) => Some(a.id),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let client = WsClient { id,
|
let client = WsClient { id,
|
||||||
tx,
|
tx,
|
||||||
account: account_id,
|
|
||||||
subs: HashSet::new(),
|
subs: HashSet::new(),
|
||||||
pvp: false,
|
pvp: false,
|
||||||
invite: None,
|
invite: None,
|
||||||
@ -183,13 +176,10 @@ impl Events {
|
|||||||
if client.subs.contains(&id) {
|
if client.subs.contains(&id) {
|
||||||
subs += 1;
|
subs += 1;
|
||||||
|
|
||||||
let redacted = match client.account {
|
let redacted = match msg {
|
||||||
Some(a) => match msg {
|
RpcMessage::InstanceState(ref i) => RpcMessage::InstanceState(i.clone().redact(client.id)),
|
||||||
RpcMessage::InstanceState(ref i) => RpcMessage::InstanceState(i.clone().redact(a)),
|
RpcMessage::GameState(ref i) => RpcMessage::GameState(i.clone().redact(client.id)),
|
||||||
RpcMessage::GameState(ref i) => RpcMessage::GameState(i.clone().redact(a)),
|
|
||||||
_ => msg.clone(),
|
_ => msg.clone(),
|
||||||
}
|
|
||||||
None => msg.clone(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match client.tx.send(redacted) {
|
match client.tx.send(redacted) {
|
||||||
@ -218,18 +208,14 @@ impl Events {
|
|||||||
let c = self.clients.get(&id)
|
let c = self.clients.get(&id)
|
||||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||||
|
|
||||||
if let None = c.account {
|
info!("pvp queue request id={:?} account={:?}", c.id, c.id);
|
||||||
return Err(err_msg("cannot join pvp queue anonymously"));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("pvp queue request id={:?} account={:?}", c.id, c.account);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the req for the already queued opponent
|
// create the req for the already queued opponent
|
||||||
if let Some(opp_req) = match self.clients.iter_mut().find(|(c_id, c)| c.pvp && **c_id != id) {
|
if let Some(opp_req) = match self.clients.iter_mut().find(|(c_id, c)| c.pvp && **c_id != id) {
|
||||||
Some((q_id, q)) => {
|
Some((q_id, q)) => {
|
||||||
q.pvp = false;
|
q.pvp = false;
|
||||||
Some(PvpRequest { id: *q_id, account: q.account.unwrap(), tx: q.tx.clone() })
|
Some(PvpRequest { id: *q_id, account: q.id, tx: q.tx.clone() })
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
} {
|
} {
|
||||||
@ -237,7 +223,7 @@ impl Events {
|
|||||||
let c = self.clients.get_mut(&id)
|
let c = self.clients.get_mut(&id)
|
||||||
.ok_or(format_err!("connection not found id={:?}", 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() };
|
let player_req = PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() };
|
||||||
self.warden.send(GameEvent::Match((opp_req, player_req)))?;
|
self.warden.send(GameEvent::Match((opp_req, player_req)))?;
|
||||||
|
|
||||||
return Ok(())
|
return Ok(())
|
||||||
@ -247,7 +233,7 @@ impl Events {
|
|||||||
let requester = self.clients.get_mut(&id).unwrap();
|
let requester = self.clients.get_mut(&id).unwrap();
|
||||||
requester.pvp = true;
|
requester.pvp = true;
|
||||||
requester.tx.send(RpcMessage::QueueJoined(()))?;
|
requester.tx.send(RpcMessage::QueueJoined(()))?;
|
||||||
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
|
info!("joined game queue id={:?} account={:?}", requester.id, requester.id);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -256,12 +242,8 @@ impl Events {
|
|||||||
let c = self.clients.get_mut(&id)
|
let c = self.clients.get_mut(&id)
|
||||||
.ok_or(format_err!("connection not found id={:?}", 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("-");
|
let code = names::name().split_whitespace().collect::<Vec<&str>>().join("-");
|
||||||
info!("pvp invite request id={:?} account={:?} code={:?}", c.id, c.account, code);
|
info!("pvp invite request id={:?} account={:?} code={:?}", c.id, c.id, code);
|
||||||
c.invite = Some(code.clone());
|
c.invite = Some(code.clone());
|
||||||
c.tx.send(RpcMessage::Invite(code))?;
|
c.tx.send(RpcMessage::Invite(code))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -272,11 +254,7 @@ impl Events {
|
|||||||
let c = self.clients.get(&id)
|
let c = self.clients.get(&id)
|
||||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||||
|
|
||||||
if let None = c.account {
|
info!("pvp join request id={:?} account={:?} code={:?}", c.id, c.id, code);
|
||||||
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()
|
let inv = self.clients.iter()
|
||||||
.filter(|(_id, c)| c.invite.is_some())
|
.filter(|(_id, c)| c.invite.is_some())
|
||||||
@ -284,10 +262,10 @@ impl Events {
|
|||||||
Some(ref c) => *c == code,
|
Some(ref c) => *c == code,
|
||||||
None => false,
|
None => false,
|
||||||
})
|
})
|
||||||
.map(|(_id, c)| PvpRequest { id: c.id, account: c.account.unwrap(), tx: c.tx.clone() })
|
.map(|(_id, c)| PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() })
|
||||||
.ok_or(format_err!("invite expired code={:?}", code))?;
|
.ok_or(format_err!("invite expired code={:?}", code))?;
|
||||||
|
|
||||||
let join = PvpRequest { id: c.id, account: c.account.unwrap(), tx: c.tx.clone() };
|
let join = PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() };
|
||||||
|
|
||||||
self.warden.send(GameEvent::Match((join, inv)))?;
|
self.warden.send(GameEvent::Match((join, inv)))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -310,7 +288,7 @@ impl Events {
|
|||||||
|
|
||||||
c.pvp = false;
|
c.pvp = false;
|
||||||
c.tx.send(RpcMessage::QueueLeft(()))?;
|
c.tx.send(RpcMessage::QueueLeft(()))?;
|
||||||
info!("left game queue id={:?} account={:?}", c.id, c.account);
|
info!("left game queue id={:?} account={:?}", c.id, c.id);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -337,12 +315,11 @@ impl Events {
|
|||||||
// now collect all listeners of this instance
|
// now collect all listeners of this instance
|
||||||
|
|
||||||
let chat_state: HashMap<Uuid, String> = self.clients.iter()
|
let chat_state: HashMap<Uuid, String> = self.clients.iter()
|
||||||
.filter(|(_id, c)| c.account.is_some())
|
|
||||||
.filter(|(_id, c)| match c.chat {
|
.filter(|(_id, c)| match c.chat {
|
||||||
Some(ref chat) => chat.0 == instance,
|
Some(ref chat) => chat.0 == instance,
|
||||||
None => false,
|
None => false,
|
||||||
})
|
})
|
||||||
.map(|(_id, c)| (c.account.unwrap(), c.chat.clone().unwrap().1))
|
.map(|(_id, c)| (c.id, c.chat.clone().unwrap().1))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
||||||
@ -357,12 +334,11 @@ impl Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chat_state: HashMap<Uuid, String> = self.clients.iter()
|
let chat_state: HashMap<Uuid, String> = self.clients.iter()
|
||||||
.filter(|(_id, c)| c.account.is_some())
|
|
||||||
.filter(|(_id, c)| match c.chat {
|
.filter(|(_id, c)| match c.chat {
|
||||||
Some(ref chat) => chat.0 == instance,
|
Some(ref chat) => chat.0 == instance,
|
||||||
None => false,
|
None => false,
|
||||||
})
|
})
|
||||||
.map(|(_id, c)| (c.account.unwrap(), c.chat.clone().unwrap().1))
|
.map(|(_id, c)| (c.id, c.chat.clone().unwrap().1))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
||||||
|
|||||||
@ -48,6 +48,8 @@ mod pg;
|
|||||||
mod events;
|
mod events;
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
mod warden;
|
mod warden;
|
||||||
|
mod user_authenticated;
|
||||||
|
mod user_anonymous;
|
||||||
|
|
||||||
use std::thread::{spawn};
|
use std::thread::{spawn};
|
||||||
use std::path::{Path};
|
use std::path::{Path};
|
||||||
|
|||||||
@ -22,7 +22,7 @@ use mnml_core::mob::instance_mobs;
|
|||||||
use mnml_core::vbox::{ItemType, VboxIndices};
|
use mnml_core::vbox::{ItemType, VboxIndices};
|
||||||
use mnml_core::item::Item;
|
use mnml_core::item::Item;
|
||||||
use mnml_core::skill::Skill;
|
use mnml_core::skill::Skill;
|
||||||
use mnml_core::mob::bot_player;
|
use mnml_core::mob::{bot_player, anon_player};
|
||||||
use mnml_core::instance::{Instance, TimeControl};
|
use mnml_core::instance::{Instance, TimeControl};
|
||||||
|
|
||||||
use events::{Event};
|
use events::{Event};
|
||||||
@ -694,6 +694,35 @@ pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result<Inst
|
|||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn instance_demo(account: &Account) -> Result<Instance, Error> {
|
||||||
|
let bot = bot_player();
|
||||||
|
let bot_id = bot.id;
|
||||||
|
|
||||||
|
// generate imgs for the client to see
|
||||||
|
for c in bot.constructs.iter() {
|
||||||
|
img::shapes_write(c.img)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut instance = Instance::new()
|
||||||
|
.set_time_control(TimeControl::Practice)
|
||||||
|
.set_name(bot.name.clone())?;
|
||||||
|
|
||||||
|
let player = anon_player(account.id);
|
||||||
|
|
||||||
|
for c in player.constructs.iter() {
|
||||||
|
img::shapes_write(c.img)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.add_player(player.clone())?;
|
||||||
|
instance.add_player(bot)?;
|
||||||
|
|
||||||
|
instance.player_ready(bot_id)?;
|
||||||
|
// skip faceoff
|
||||||
|
instance.player_ready(player.id)?;
|
||||||
|
|
||||||
|
Ok(instance)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pvp(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()
|
let mut instance = Instance::new()
|
||||||
// TODO generate nice game names
|
// TODO generate nice game names
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use mnml_core::item::ItemInfoCtr;
|
use mnml_core::item::ItemInfoCtr;
|
||||||
use mnml_core::instance::ChatState;
|
use mnml_core::instance::ChatState;
|
||||||
use mnml_core::item::item_info;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::{Instant};
|
use std::time::{Instant};
|
||||||
use std::thread::{spawn};
|
use std::thread::{spawn};
|
||||||
@ -8,12 +8,8 @@ use std::thread::{spawn};
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use rand::prelude::*;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use serde_cbor::{to_vec};
|
||||||
|
|
||||||
use serde_cbor::{from_slice, to_vec};
|
|
||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
|
|
||||||
use stripe::{Client as StripeClient, Subscription};
|
use stripe::{Client as StripeClient, Subscription};
|
||||||
@ -22,42 +18,24 @@ use crossbeam_channel::{unbounded, Sender as CbSender};
|
|||||||
use ws::{Builder, CloseCode, Message, Handler, Request, Response, Settings, Sender as WsSender};
|
use ws::{Builder, CloseCode, Message, Handler, Request, Response, Settings, Sender as WsSender};
|
||||||
use ws::deflate::DeflateHandler;
|
use ws::deflate::DeflateHandler;
|
||||||
|
|
||||||
use pg::{
|
|
||||||
game_concede,
|
|
||||||
game_offer_draw,
|
|
||||||
game_ready,
|
|
||||||
game_skill,
|
|
||||||
game_skill_clear,
|
|
||||||
game_state,
|
|
||||||
instance_abandon,
|
|
||||||
instance_practice,
|
|
||||||
instance_ready,
|
|
||||||
instance_state,
|
|
||||||
vbox_apply,
|
|
||||||
vbox_buy,
|
|
||||||
vbox_combine,
|
|
||||||
vbox_refill,
|
|
||||||
vbox_refund,
|
|
||||||
vbox_unequip,
|
|
||||||
};
|
|
||||||
|
|
||||||
use account::{Account};
|
use account::{Account};
|
||||||
use account;
|
use account;
|
||||||
use events::{Event};
|
use events::{Event};
|
||||||
|
|
||||||
|
use user_anonymous::{Anonymous};
|
||||||
|
use user_authenticated::{Authorised};
|
||||||
|
|
||||||
use mnml_core::construct::{Construct};
|
use mnml_core::construct::{Construct};
|
||||||
use mnml_core::game::{Game};
|
use mnml_core::game::{Game};
|
||||||
|
|
||||||
use mnml_core::vbox::{ItemType};
|
use mnml_core::vbox::{ItemType};
|
||||||
use mnml_core::item::Item;
|
use mnml_core::item::Item;
|
||||||
use mnml_core::skill::Skill;
|
use mnml_core::skill::Skill;
|
||||||
use mnml_core::mob::{anim_test_game};
|
|
||||||
use mnml_core::instance::{Instance};
|
use mnml_core::instance::{Instance};
|
||||||
|
|
||||||
use mtx;
|
use mtx;
|
||||||
use mail;
|
|
||||||
|
|
||||||
use payments;
|
|
||||||
use mail::Email;
|
use mail::Email;
|
||||||
use pg::{Db};
|
use pg::{Db};
|
||||||
use pg::{PgPool};
|
use pg::{PgPool};
|
||||||
@ -145,194 +123,32 @@ pub enum RpcRequest {
|
|||||||
VboxRefund { instance_id: Uuid, index: String },
|
VboxRefund { instance_id: Uuid, index: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait User {
|
||||||
|
fn receive(&mut self, data: Vec<u8>, db: &Db, begin: Instant, events: &CbSender<Event>, stripe: &StripeClient) -> Result<RpcMessage, Error>;
|
||||||
|
fn connected(&mut self, db: &Db, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error>;
|
||||||
|
fn send(&mut self, msg: RpcMessage, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
struct Connection {
|
struct Connection {
|
||||||
pub id: usize,
|
pub id: Uuid,
|
||||||
pub ws: CbSender<RpcMessage>,
|
pub ws: CbSender<RpcMessage>,
|
||||||
pool: PgPool,
|
pool: PgPool,
|
||||||
stripe: StripeClient,
|
stripe: StripeClient,
|
||||||
account: Option<Account>,
|
// account: Option<Account>,
|
||||||
|
user: Box<dyn User>,
|
||||||
events: CbSender<Event>,
|
events: CbSender<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
fn receive(&self, data: Vec<u8>, db: &Db, begin: Instant) -> Result<RpcMessage, Error> {
|
|
||||||
// cast the msg to this type to receive method name
|
|
||||||
match from_slice::<RpcRequest>(&data) {
|
|
||||||
Ok(v) => {
|
|
||||||
|
|
||||||
// non authenticated
|
|
||||||
// non transactional reqs
|
|
||||||
match v {
|
|
||||||
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
|
|
||||||
RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())),
|
|
||||||
RpcRequest::DevResolve { skill } =>
|
|
||||||
return Ok(RpcMessage::GameState(anim_test_game(skill))),
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
// check for authorization now
|
|
||||||
let account = match self.account {
|
|
||||||
Some(ref account) => account,
|
|
||||||
None => return Err(err_msg("auth required")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let request = v.clone();
|
|
||||||
|
|
||||||
let response = match v {
|
|
||||||
// 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(()))
|
|
||||||
},
|
|
||||||
RpcRequest::InstanceLeave {} => {
|
|
||||||
self.events.send(Event::Leave(self.id))?;
|
|
||||||
Ok(RpcMessage::Processing(()))
|
|
||||||
},
|
|
||||||
|
|
||||||
RpcRequest::InstanceChat { instance_id, index } => {
|
|
||||||
if !account.subscribed {
|
|
||||||
return Err(err_msg("subscribe to unlock chat"))
|
|
||||||
}
|
|
||||||
|
|
||||||
let wheel = account::chat_wheel(&db, account.id)?;
|
|
||||||
|
|
||||||
if let Some(c) = wheel.get(index) {
|
|
||||||
self.events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
|
|
||||||
} else {
|
|
||||||
return Err(err_msg("invalid chat index"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RpcMessage::Processing(()))
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
// all good, let's make a tx and process
|
|
||||||
let mut tx = db.transaction()?;
|
|
||||||
|
|
||||||
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::EmailState {} =>
|
|
||||||
Ok(RpcMessage::EmailState(mail::select_account(&db, account.id)?)),
|
|
||||||
|
|
||||||
RpcRequest::SubscriptionState {} =>
|
|
||||||
Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, &self.stripe, &account)?)),
|
|
||||||
|
|
||||||
// RpcRequest::AccountShop {} =>
|
|
||||||
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
|
||||||
|
|
||||||
// RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account),
|
|
||||||
|
|
||||||
RpcRequest::GameState { id } =>
|
|
||||||
Ok(RpcMessage::GameState(game_state(&mut tx, account, 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::GameSkillClear { game_id } =>
|
|
||||||
Ok(RpcMessage::GameState(game_skill_clear(&mut tx, account, game_id)?)),
|
|
||||||
|
|
||||||
RpcRequest::GameReady { id } =>
|
|
||||||
Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)),
|
|
||||||
|
|
||||||
RpcRequest::GameConcede { game_id } =>
|
|
||||||
Ok(RpcMessage::GameState(game_concede(&mut tx, account, game_id)?)),
|
|
||||||
|
|
||||||
RpcRequest::GameOfferDraw { game_id } =>
|
|
||||||
Ok(RpcMessage::GameState(game_offer_draw(&mut tx, account, game_id)?)),
|
|
||||||
|
|
||||||
RpcRequest::InstancePractice {} =>
|
|
||||||
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, account)?)),
|
|
||||||
|
|
||||||
// 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::VboxBuy { instance_id, group, index, construct_id } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_buy(&mut tx, account, instance_id, group, index, construct_id)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxApply { instance_id, construct_id, index } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, account, instance_id, construct_id, index)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxCombine { instance_id, inv_indices, vbox_indices } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, account, instance_id, inv_indices, vbox_indices)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxRefill { instance_id } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_refill(&mut tx, account, instance_id)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxRefund { instance_id, index } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_refund(&mut tx, account, instance_id, index)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxUnequip { instance_id, construct_id, target } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, account, instance_id, construct_id, target, None)?)),
|
|
||||||
|
|
||||||
RpcRequest::VboxUnequipApply { instance_id, construct_id, target, target_construct_id } =>
|
|
||||||
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, account, instance_id, construct_id, target, Some(target_construct_id))?)),
|
|
||||||
|
|
||||||
RpcRequest::MtxConstructSpawn {} =>
|
|
||||||
Ok(RpcMessage::ConstructSpawn(mtx::new_construct(&mut tx, account)?)),
|
|
||||||
|
|
||||||
RpcRequest::MtxConstructApply { mtx, construct_id, name } =>
|
|
||||||
Ok(RpcMessage::AccountTeam(mtx::apply(&mut tx, account, mtx, construct_id, name)?)),
|
|
||||||
|
|
||||||
RpcRequest::MtxAccountApply { mtx } =>
|
|
||||||
Ok(RpcMessage::AccountState(mtx::account_apply(&mut tx, account, mtx)?)),
|
|
||||||
|
|
||||||
RpcRequest::MtxBuy { mtx } =>
|
|
||||||
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
info!("request={:?} account={:?} duration={:?}", request, account.name, begin.elapsed());
|
|
||||||
|
|
||||||
return response;
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
warn!("{:?}", e);
|
|
||||||
Err(err_msg("invalid message"))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is where last minute processing happens
|
// this is where last minute processing happens
|
||||||
// use it to modify outgoing messages, update subs, serialize in some way...
|
// use it to modify outgoing messages, update subs, serialize in some way...
|
||||||
fn send(&self, msg: RpcMessage) -> Result<(), Error> {
|
fn send(&self, msg: RpcMessage) -> Result<(), Error> {
|
||||||
let msg = match self.account {
|
let msg = match msg {
|
||||||
Some(ref a) => match msg {
|
RpcMessage::InstanceState(v) => RpcMessage::InstanceState(v.redact(self.id)),
|
||||||
RpcMessage::InstanceState(v) => RpcMessage::InstanceState(v.redact(a.id)),
|
|
||||||
RpcMessage::AccountInstances(v) =>
|
RpcMessage::AccountInstances(v) =>
|
||||||
RpcMessage::AccountInstances(v.into_iter().map(|i| i.redact(a.id)).collect()),
|
RpcMessage::AccountInstances(v.into_iter().map(|i| i.redact(self.id)).collect()),
|
||||||
RpcMessage::GameState(v) => RpcMessage::GameState(v.redact(a.id)),
|
RpcMessage::GameState(v) => RpcMessage::GameState(v.redact(self.id)),
|
||||||
_ => msg,
|
_ => msg,
|
||||||
},
|
|
||||||
None => msg,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.ws.send(msg).unwrap();
|
self.ws.send(msg).unwrap();
|
||||||
@ -347,48 +163,8 @@ impl Connection {
|
|||||||
// when it encounters errors
|
// when it encounters errors
|
||||||
impl Handler for Connection {
|
impl Handler for Connection {
|
||||||
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
|
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
|
||||||
info!("websocket connected account={:?}", self.account);
|
|
||||||
|
|
||||||
// tell events we have connected
|
|
||||||
self.events.send(Event::Connect(self.id, self.account.clone(), self.ws.clone())).unwrap();
|
|
||||||
|
|
||||||
// if user logged in do some prep work
|
|
||||||
if let Some(ref a) = self.account {
|
|
||||||
self.send(RpcMessage::AccountState(a.clone())).unwrap();
|
|
||||||
self.events.send(Event::Subscribe(self.id, a.id)).unwrap();
|
|
||||||
|
|
||||||
// check if they have an image that needs to be generated
|
|
||||||
account::img_check(&a).unwrap();
|
|
||||||
|
|
||||||
let db = self.pool.get().unwrap();
|
let db = self.pool.get().unwrap();
|
||||||
let mut tx = db.transaction().unwrap();
|
self.user.connected(&db, &self.events, &self.ws).unwrap();
|
||||||
|
|
||||||
// send account constructs
|
|
||||||
let account_constructs = account::constructs(&mut tx, a).unwrap();
|
|
||||||
self.send(RpcMessage::AccountConstructs(account_constructs)).unwrap();
|
|
||||||
|
|
||||||
// get account instances
|
|
||||||
// and send them to the client
|
|
||||||
let account_instances = account::account_instances(&mut tx, a).unwrap();
|
|
||||||
self.send(RpcMessage::AccountInstances(account_instances)).unwrap();
|
|
||||||
|
|
||||||
let shop = mtx::account_shop(&mut tx, &a).unwrap();
|
|
||||||
self.send(RpcMessage::AccountShop(shop)).unwrap();
|
|
||||||
|
|
||||||
let team = account::team(&mut tx, &a).unwrap();
|
|
||||||
self.send(RpcMessage::AccountTeam(team)).unwrap();
|
|
||||||
|
|
||||||
let wheel = account::chat_wheel(&db, a.id).unwrap();
|
|
||||||
self.send(RpcMessage::ChatWheel(wheel)).unwrap();
|
|
||||||
|
|
||||||
if let Some(instance) = account::tutorial(&mut tx, &a).unwrap() {
|
|
||||||
self.send(RpcMessage::InstanceState(instance)).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// tx should do nothing
|
|
||||||
tx.commit().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,23 +174,9 @@ impl Handler for Connection {
|
|||||||
let begin = Instant::now();
|
let begin = Instant::now();
|
||||||
let db_connection = self.pool.get().unwrap();
|
let db_connection = self.pool.get().unwrap();
|
||||||
|
|
||||||
match self.receive(msg, &db_connection, begin) {
|
match self.user.receive(msg, &db_connection, begin, &self.events, &self.stripe) {
|
||||||
Ok(reply) => {
|
Ok(msg) => {
|
||||||
// if the user queries the state of something
|
self.user.send(msg, &self.events, &self.ws).unwrap();
|
||||||
// we tell events to push updates to them
|
|
||||||
match reply {
|
|
||||||
RpcMessage::AccountState(ref v) => {
|
|
||||||
self.account = Some(v.clone());
|
|
||||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap()
|
|
||||||
},
|
|
||||||
RpcMessage::GameState(ref v) =>
|
|
||||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
|
||||||
RpcMessage::InstanceState(ref v) =>
|
|
||||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.send(reply).unwrap();
|
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
@ -428,7 +190,7 @@ impl Handler for Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_close(&mut self, _: CloseCode, _: &str) {
|
fn on_close(&mut self, _: CloseCode, _: &str) {
|
||||||
info!("websocket disconnected account={:?}", self.account);
|
info!("websocket disconnected id={:?}", self.id);
|
||||||
self.events.send(Event::Disconnect(self.id)).unwrap();
|
self.events.send(Event::Disconnect(self.id)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,21 +218,19 @@ impl Handler for Connection {
|
|||||||
if cookie.name() == TOKEN_HEADER {
|
if cookie.name() == TOKEN_HEADER {
|
||||||
let db = self.pool.get().unwrap();
|
let db = self.pool.get().unwrap();
|
||||||
match account::from_token(&db, &cookie.value().to_string()) {
|
match account::from_token(&db, &cookie.value().to_string()) {
|
||||||
Ok(a) => self.account = Some(a),
|
Ok(a) => self.user = Box::new(Authorised { id: a.id, account: a }),
|
||||||
Err(_) => return unauth(),
|
Err(_) => return unauth(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
||||||
let mut rng = thread_rng();
|
let _ws = Builder::new()
|
||||||
|
|
||||||
let ws = Builder::new()
|
|
||||||
.with_settings(Settings {
|
.with_settings(Settings {
|
||||||
max_connections: 10_000,
|
max_connections: 10_000,
|
||||||
..Settings::default()
|
..Settings::default()
|
||||||
@ -500,14 +260,17 @@ pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let anon_account = Account::anonymous();
|
||||||
|
let id = anon_account.id;
|
||||||
|
|
||||||
DeflateHandler::new(
|
DeflateHandler::new(
|
||||||
Connection {
|
Connection {
|
||||||
id: rng.gen::<usize>(),
|
id,
|
||||||
account: None,
|
|
||||||
ws: tx,
|
ws: tx,
|
||||||
pool: pool.clone(),
|
pool: pool.clone(),
|
||||||
stripe: stripe.clone(),
|
stripe: stripe.clone(),
|
||||||
events: events_tx.clone(),
|
events: events_tx.clone(),
|
||||||
|
user: Box::new(Anonymous { id, account: anon_account, game: None, instance: None })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
148
server/src/user_anonymous.rs
Normal file
148
server/src/user_anonymous.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
use std::time::Instant;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
|
|
||||||
|
use crossbeam_channel::{Sender as CbSender};
|
||||||
|
|
||||||
|
use serde_cbor::{from_slice};
|
||||||
|
|
||||||
|
use stripe::{Client as StripeClient};
|
||||||
|
|
||||||
|
use account::{Account};
|
||||||
|
use pg::{Db};
|
||||||
|
use pg;
|
||||||
|
use events::{Event};
|
||||||
|
use rpc::{RpcMessage, RpcRequest, User};
|
||||||
|
|
||||||
|
use mnml_core::game::Game;
|
||||||
|
use mnml_core::item::item_info;
|
||||||
|
use mnml_core::instance::Instance;
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct Anonymous {
|
||||||
|
pub account: Account,
|
||||||
|
pub id: Uuid,
|
||||||
|
pub instance: Option<Instance>,
|
||||||
|
pub game: Option<Game>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User for Anonymous {
|
||||||
|
fn send(&mut self, msg: RpcMessage, _events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error> {
|
||||||
|
// if the user queries the state of something
|
||||||
|
// we tell events to push updates to them
|
||||||
|
match msg {
|
||||||
|
RpcMessage::GameState(ref v) =>
|
||||||
|
self.game = Some(v.clone()),
|
||||||
|
RpcMessage::InstanceState(ref v) =>
|
||||||
|
self.instance = Some(v.clone()),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.send(msg)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connected(&mut self, _db: &Db, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error> {
|
||||||
|
info!("anonymous connection");
|
||||||
|
|
||||||
|
self.send(RpcMessage::AccountState(self.account.clone()), events, ws)?;
|
||||||
|
self.send(RpcMessage::ItemInfo(item_info()), events, ws)?;
|
||||||
|
self.send(RpcMessage::InstanceState(pg::instance_demo(&self.account)?), events, ws)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&mut self, data: Vec<u8>, _db: &Db, _begin: Instant, _events: &CbSender<Event>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||||
|
match from_slice::<RpcRequest>(&data) {
|
||||||
|
Ok(v) => {
|
||||||
|
let mut instance = match self.instance {
|
||||||
|
Some(ref i) => i.clone(),
|
||||||
|
None => return Err(err_msg("instance missing")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let game = match self.game {
|
||||||
|
Some(ref i) => Some(i.clone()),
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
|
||||||
|
match v {
|
||||||
|
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
|
||||||
|
|
||||||
|
RpcRequest::InstanceReady { instance_id: _ } => {
|
||||||
|
match instance.player_ready(self.account.id)? {
|
||||||
|
Some(g) => Ok(RpcMessage::GameState(g)),
|
||||||
|
None => Ok(RpcMessage::InstanceState(instance)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
RpcRequest::InstanceState { instance_id: _ } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance)),
|
||||||
|
|
||||||
|
RpcRequest::InstanceAbandon { instance_id: _ } =>
|
||||||
|
Err(err_msg("don't give up!")),
|
||||||
|
|
||||||
|
RpcRequest::VboxBuy { instance_id: _, group, index, construct_id } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_buy(self.account.id, group, index, construct_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxApply { instance_id: _, construct_id, index } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_apply(self.account.id, index, construct_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxCombine { instance_id: _, inv_indices, vbox_indices } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_combine(self.account.id, inv_indices, vbox_indices)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxRefill { instance_id: _ } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_refill(self.account.id)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxRefund { instance_id: _, index } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_refund(self.account.id, index)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxUnequip { instance_id: _, construct_id, target } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_unequip(self.account.id, target, construct_id, None)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxUnequipApply { instance_id: _, construct_id, target, target_construct_id } =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance.vbox_unequip(self.account.id, target, construct_id, Some(target_construct_id))?)),
|
||||||
|
|
||||||
|
RpcRequest::GameState { id: _ } =>
|
||||||
|
Ok(RpcMessage::GameState(game.unwrap())),
|
||||||
|
|
||||||
|
RpcRequest::GameSkill { game_id: _, construct_id, target_construct_id, skill } => {
|
||||||
|
let mut game = game.unwrap();
|
||||||
|
game.add_skill(self.account.id, construct_id, target_construct_id, skill)?;
|
||||||
|
Ok(RpcMessage::GameState(game))
|
||||||
|
},
|
||||||
|
|
||||||
|
RpcRequest::GameSkillClear { game_id: _ } => {
|
||||||
|
let mut game = game.unwrap();
|
||||||
|
game.clear_skill(self.account.id)?;
|
||||||
|
Ok(RpcMessage::GameState(game))
|
||||||
|
},
|
||||||
|
|
||||||
|
RpcRequest::GameReady { id: _ } => {
|
||||||
|
let mut game = game.unwrap();
|
||||||
|
game.player_ready(self.account.id)?;
|
||||||
|
if game.skill_phase_finished() {
|
||||||
|
game = game.resolve_phase_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RpcMessage::GameState(game))
|
||||||
|
},
|
||||||
|
|
||||||
|
RpcRequest::GameConcede { game_id: _ } =>
|
||||||
|
Ok(RpcMessage::GameState(game.unwrap().concede(self.account.id)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameOfferDraw { game_id: _ } =>
|
||||||
|
Ok(RpcMessage::GameState(game.unwrap().offer_draw(self.account.id)?)),
|
||||||
|
|
||||||
|
_ => Err(format_err!("unhandled anonymous request request={:?}", v)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
Err(err_msg("invalid message"))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
264
server/src/user_authenticated.rs
Normal file
264
server/src/user_authenticated.rs
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
use mnml_core::mob::anim_test_game;
|
||||||
|
use mnml_core::item::item_info;
|
||||||
|
use std::time::Instant;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
|
|
||||||
|
use crossbeam_channel::{Sender as CbSender};
|
||||||
|
use stripe::{Client as StripeClient};
|
||||||
|
|
||||||
|
use serde_cbor::{from_slice};
|
||||||
|
|
||||||
|
use pg::{
|
||||||
|
game_concede,
|
||||||
|
game_offer_draw,
|
||||||
|
game_ready,
|
||||||
|
game_skill,
|
||||||
|
game_skill_clear,
|
||||||
|
game_state,
|
||||||
|
instance_abandon,
|
||||||
|
instance_practice,
|
||||||
|
instance_ready,
|
||||||
|
instance_state,
|
||||||
|
vbox_apply,
|
||||||
|
vbox_buy,
|
||||||
|
vbox_combine,
|
||||||
|
vbox_refill,
|
||||||
|
vbox_refund,
|
||||||
|
vbox_unequip,
|
||||||
|
};
|
||||||
|
|
||||||
|
use account::{Account};
|
||||||
|
use account;
|
||||||
|
use events::{Event};
|
||||||
|
|
||||||
|
use mtx;
|
||||||
|
use mail;
|
||||||
|
use payments;
|
||||||
|
use pg::{Db};
|
||||||
|
use rpc::{RpcMessage, RpcRequest, User};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct Authorised {
|
||||||
|
pub account: Account,
|
||||||
|
pub id: Uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User for Authorised {
|
||||||
|
fn send(&mut self, msg: RpcMessage, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error> {
|
||||||
|
// if the user queries the state of something
|
||||||
|
// we tell events to push updates to them
|
||||||
|
match msg {
|
||||||
|
RpcMessage::AccountState(ref v) => {
|
||||||
|
events.send(Event::Subscribe(self.id, v.id))?
|
||||||
|
},
|
||||||
|
RpcMessage::GameState(ref v) =>
|
||||||
|
events.send(Event::Subscribe(self.id, v.id))?,
|
||||||
|
RpcMessage::InstanceState(ref v) =>
|
||||||
|
events.send(Event::Subscribe(self.id, v.id))?,
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.send(msg)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connected(&mut self, db: &Db, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error> {
|
||||||
|
info!("authenticated connection account={:?}", self.account);
|
||||||
|
let a = &self.account;
|
||||||
|
|
||||||
|
// tell events we have connected
|
||||||
|
events.send(Event::Connect(self.id, a.clone(), ws.clone()))?;
|
||||||
|
|
||||||
|
ws.send(RpcMessage::AccountState(a.clone()))?;
|
||||||
|
events.send(Event::Subscribe(self.id, a.id))?;
|
||||||
|
|
||||||
|
// check if they have an image that needs to be generated
|
||||||
|
account::img_check(&a)?;
|
||||||
|
|
||||||
|
let mut tx = db.transaction()?;
|
||||||
|
|
||||||
|
// send account constructs
|
||||||
|
let account_constructs = account::constructs(&mut tx, &a)?;
|
||||||
|
ws.send(RpcMessage::AccountConstructs(account_constructs))?;
|
||||||
|
|
||||||
|
// get account instances
|
||||||
|
// and send them to the client
|
||||||
|
let account_instances = account::account_instances(&mut tx, &a)?;
|
||||||
|
ws.send(RpcMessage::AccountInstances(account_instances))?;
|
||||||
|
|
||||||
|
let shop = mtx::account_shop(&mut tx, &a)?;
|
||||||
|
ws.send(RpcMessage::AccountShop(shop))?;
|
||||||
|
|
||||||
|
let team = account::team(&mut tx, &a)?;
|
||||||
|
ws.send(RpcMessage::AccountTeam(team))?;
|
||||||
|
|
||||||
|
let wheel = account::chat_wheel(&db, a.id)?;
|
||||||
|
ws.send(RpcMessage::ChatWheel(wheel))?;
|
||||||
|
|
||||||
|
if let Some(instance) = account::tutorial(&mut tx, &a)? {
|
||||||
|
ws.send(RpcMessage::InstanceState(instance))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tx should do nothing
|
||||||
|
tx.commit()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&mut self, data: Vec<u8>, db: &Db, begin: Instant, events: &CbSender<Event>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||||
|
// cast the msg to this type to receive method name
|
||||||
|
match from_slice::<RpcRequest>(&data) {
|
||||||
|
Ok(v) => {
|
||||||
|
let request = v.clone();
|
||||||
|
let response = match v {
|
||||||
|
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
|
||||||
|
RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())),
|
||||||
|
RpcRequest::DevResolve { skill } =>
|
||||||
|
return Ok(RpcMessage::GameState(anim_test_game(skill))),
|
||||||
|
|
||||||
|
RpcRequest::InstanceQueue {} => {
|
||||||
|
events.send(Event::Queue(self.id))?;
|
||||||
|
Ok(RpcMessage::QueueRequested(()))
|
||||||
|
},
|
||||||
|
RpcRequest::InstanceInvite {} => {
|
||||||
|
events.send(Event::Invite(self.id))?;
|
||||||
|
Ok(RpcMessage::InviteRequested(()))
|
||||||
|
},
|
||||||
|
RpcRequest::InstanceJoin { code } => {
|
||||||
|
events.send(Event::Join(self.id, code))?;
|
||||||
|
Ok(RpcMessage::Joining(()))
|
||||||
|
},
|
||||||
|
RpcRequest::InstanceLeave {} => {
|
||||||
|
events.send(Event::Leave(self.id))?;
|
||||||
|
Ok(RpcMessage::Processing(()))
|
||||||
|
},
|
||||||
|
|
||||||
|
RpcRequest::InstanceChat { instance_id, index } => {
|
||||||
|
if !self.account.subscribed {
|
||||||
|
return Err(err_msg("subscribe to unlock chat"))
|
||||||
|
}
|
||||||
|
|
||||||
|
let wheel = account::chat_wheel(&db, self.account.id)?;
|
||||||
|
|
||||||
|
if let Some(c) = wheel.get(index) {
|
||||||
|
events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
|
||||||
|
} else {
|
||||||
|
return Err(err_msg("invalid chat index"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RpcMessage::Processing(()))
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// all good, let's make a tx and process
|
||||||
|
let mut tx = db.transaction()?;
|
||||||
|
|
||||||
|
let res = match v {
|
||||||
|
RpcRequest::AccountState {} =>
|
||||||
|
Ok(RpcMessage::AccountState(self.account.clone())),
|
||||||
|
RpcRequest::AccountConstructs {} =>
|
||||||
|
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &self.account)?)),
|
||||||
|
RpcRequest::AccountInstances {} =>
|
||||||
|
Ok(RpcMessage::AccountInstances(account::account_instances(&mut tx, &self.account)?)),
|
||||||
|
RpcRequest::AccountSetTeam { ids } =>
|
||||||
|
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &self.account, ids)?)),
|
||||||
|
|
||||||
|
RpcRequest::EmailState {} =>
|
||||||
|
Ok(RpcMessage::EmailState(mail::select_account(&db, self.account.id)?)),
|
||||||
|
|
||||||
|
RpcRequest::SubscriptionState {} =>
|
||||||
|
Ok(RpcMessage::SubscriptionState(payments::account_subscription(db, stripe, &self.account)?)),
|
||||||
|
|
||||||
|
// RpcRequest::AccountShop {} =>
|
||||||
|
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
||||||
|
|
||||||
|
// RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account),
|
||||||
|
|
||||||
|
RpcRequest::GameState { id } =>
|
||||||
|
Ok(RpcMessage::GameState(game_state(&mut tx, &self.account, id)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameSkill { game_id, construct_id, target_construct_id, skill } =>
|
||||||
|
Ok(RpcMessage::GameState(game_skill(&mut tx, &self.account, game_id, construct_id, target_construct_id, skill)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameSkillClear { game_id } =>
|
||||||
|
Ok(RpcMessage::GameState(game_skill_clear(&mut tx, &self.account, game_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameReady { id } =>
|
||||||
|
Ok(RpcMessage::GameState(game_ready(&mut tx, &self.account, id)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameConcede { game_id } =>
|
||||||
|
Ok(RpcMessage::GameState(game_concede(&mut tx, &self.account, game_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::GameOfferDraw { game_id } =>
|
||||||
|
Ok(RpcMessage::GameState(game_offer_draw(&mut tx, &self.account, game_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::InstancePractice {} =>
|
||||||
|
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, &self.account)?)),
|
||||||
|
|
||||||
|
// these two can return GameState or InstanceState
|
||||||
|
RpcRequest::InstanceReady { instance_id } =>
|
||||||
|
Ok(instance_ready(&mut tx, &self.account, instance_id)?),
|
||||||
|
RpcRequest::InstanceState { instance_id } =>
|
||||||
|
Ok(instance_state(&mut tx, instance_id)?),
|
||||||
|
RpcRequest::InstanceAbandon { instance_id } =>
|
||||||
|
Ok(instance_abandon(&mut tx, &self.account, instance_id)?),
|
||||||
|
|
||||||
|
RpcRequest::VboxBuy { instance_id, group, index, construct_id } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_buy(&mut tx, &self.account, instance_id, group, index, construct_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxApply { instance_id, construct_id, index } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, &self.account, instance_id, construct_id, index)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxCombine { instance_id, inv_indices, vbox_indices } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, &self.account, instance_id, inv_indices, vbox_indices)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxRefill { instance_id } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_refill(&mut tx, &self.account, instance_id)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxRefund { instance_id, index } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_refund(&mut tx, &self.account, instance_id, index)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxUnequip { instance_id, construct_id, target } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, &self.account, instance_id, construct_id, target, None)?)),
|
||||||
|
|
||||||
|
RpcRequest::VboxUnequipApply { instance_id, construct_id, target, target_construct_id } =>
|
||||||
|
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, &self.account, instance_id, construct_id, target, Some(target_construct_id))?)),
|
||||||
|
|
||||||
|
RpcRequest::MtxConstructSpawn {} =>
|
||||||
|
Ok(RpcMessage::ConstructSpawn(mtx::new_construct(&mut tx, &self.account)?)),
|
||||||
|
|
||||||
|
RpcRequest::MtxConstructApply { mtx, construct_id, name } =>
|
||||||
|
Ok(RpcMessage::AccountTeam(mtx::apply(&mut tx, &self.account, mtx, construct_id, name)?)),
|
||||||
|
|
||||||
|
RpcRequest::MtxAccountApply { mtx } =>
|
||||||
|
Ok(RpcMessage::AccountState(mtx::account_apply(&mut tx, &self.account, mtx)?)),
|
||||||
|
|
||||||
|
RpcRequest::MtxBuy { mtx } =>
|
||||||
|
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, &self.account, mtx)?)),
|
||||||
|
|
||||||
|
RpcRequest::SubscriptionEnding { ending } =>
|
||||||
|
Ok(RpcMessage::SubscriptionState(payments::subscription_ending(&mut tx, stripe, &self.account, ending)?)),
|
||||||
|
|
||||||
|
_ => Err(format_err!("unknown request request={:?}", request)),
|
||||||
|
};
|
||||||
|
|
||||||
|
tx.commit()?;
|
||||||
|
res
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("request={:?} account={:?} duration={:?}", request, self.account.name, begin.elapsed());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
Err(err_msg("invalid message"))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user