187 lines
6.9 KiB
Rust
187 lines
6.9 KiB
Rust
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;
|
|
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>,
|
|
|
|
ws: CbSender<RpcMessage>,
|
|
}
|
|
|
|
impl Anonymous {
|
|
pub fn new(account: Account, ws: CbSender<RpcMessage>) -> Anonymous {
|
|
Anonymous {
|
|
id: account.id,
|
|
account,
|
|
ws,
|
|
instance: None,
|
|
game: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl User for Anonymous {
|
|
fn send(&mut self, msg: 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()),
|
|
_ => (),
|
|
};
|
|
|
|
// last minute redactions and processing
|
|
// this happens after the state setting as we need to keep
|
|
// all the skills to prevent forfeiting
|
|
let msg = match msg {
|
|
RpcMessage::InstanceState(v) => RpcMessage::InstanceState(v.redact(self.id)),
|
|
RpcMessage::GameState(v) => RpcMessage::GameState(v.redact(self.id)),
|
|
_ => msg,
|
|
};
|
|
|
|
|
|
self.ws.send(msg)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn connected(&mut self) -> Result<(), Error> {
|
|
info!("anonymous connection");
|
|
|
|
self.ws.send(RpcMessage::AccountState(self.account.clone()))?;
|
|
Ok(())
|
|
}
|
|
|
|
fn disconnected(&self) -> Result<(), Error> {
|
|
Ok(())
|
|
}
|
|
|
|
fn receive(&mut self, data: Vec<u8>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
|
match from_slice::<RpcRequest>(&data) {
|
|
Ok(v) => {
|
|
let get_instance = || {
|
|
match self.instance {
|
|
Some(ref i) => Ok(i.clone()),
|
|
None => return Err(err_msg("instance missing")),
|
|
}
|
|
};
|
|
|
|
let get_game = || {
|
|
match self.game {
|
|
Some(ref i) => Ok(i.clone()),
|
|
None => return Err(err_msg("game missing")),
|
|
}
|
|
};
|
|
|
|
match v {
|
|
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
|
|
|
|
RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())),
|
|
RpcRequest::AccountInstances {} => return Ok(RpcMessage::Pong(())),
|
|
|
|
RpcRequest::InstancePractice {} =>
|
|
Ok(RpcMessage::InstanceState(pg::instance_demo(&self.account)?)),
|
|
|
|
RpcRequest::InstanceReady { instance_id: _ } => {
|
|
match get_instance()?.player_ready(self.account.id)? {
|
|
Some(g) => Ok(RpcMessage::GameState(g)),
|
|
None => Ok(RpcMessage::InstanceState(get_instance()?)),
|
|
}
|
|
},
|
|
|
|
RpcRequest::InstanceState { instance_id: _ } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?)),
|
|
|
|
RpcRequest::InstanceAbandon { instance_id: _ } => {
|
|
let mut instance = get_instance()?;
|
|
instance.finish();
|
|
Ok(RpcMessage::InstanceState(instance))
|
|
},
|
|
|
|
RpcRequest::VboxBuy { instance_id: _, group, index, construct_id } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_buy(self.account.id, group, index, construct_id)?)),
|
|
|
|
RpcRequest::VboxApply { instance_id: _, construct_id, index } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_apply(self.account.id, index, construct_id)?)),
|
|
|
|
RpcRequest::VboxCombine { instance_id: _, inv_indices, vbox_indices } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_combine(self.account.id, inv_indices, vbox_indices)?)),
|
|
|
|
RpcRequest::VboxRefill { instance_id: _ } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_refill(self.account.id)?)),
|
|
|
|
RpcRequest::VboxRefund { instance_id: _, index } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_refund(self.account.id, index)?)),
|
|
|
|
RpcRequest::VboxUnequip { instance_id: _, construct_id, target } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_unequip(self.account.id, target, construct_id, None)?)),
|
|
|
|
RpcRequest::VboxUnequipApply { instance_id: _, construct_id, target, target_construct_id } =>
|
|
Ok(RpcMessage::InstanceState(get_instance()?.vbox_unequip(self.account.id, target, construct_id, Some(target_construct_id))?)),
|
|
|
|
RpcRequest::GameState { id: _ } =>
|
|
Ok(RpcMessage::GameState(get_game()?)),
|
|
|
|
RpcRequest::GameSkill { game_id: _, construct_id, target_construct_id, skill } => {
|
|
let mut game = get_game()?;
|
|
game.add_skill(self.account.id, construct_id, target_construct_id, skill)?;
|
|
Ok(RpcMessage::GameState(game))
|
|
},
|
|
|
|
RpcRequest::GameSkillClear { game_id: _ } => {
|
|
let mut game = get_game()?;
|
|
game.clear_skill(self.account.id)?;
|
|
Ok(RpcMessage::GameState(game))
|
|
},
|
|
|
|
RpcRequest::GameReady { id: _ } => {
|
|
let mut game = get_game()?;
|
|
game.player_ready(self.account.id)?;
|
|
if game.skill_phase_finished() {
|
|
game = game.resolve_phase_start();
|
|
}
|
|
|
|
if game.finished() {
|
|
self.ws.send(RpcMessage::PromptRegister(()))?;
|
|
}
|
|
|
|
Ok(RpcMessage::GameState(game))
|
|
},
|
|
|
|
RpcRequest::GameConcede { game_id: _ } =>
|
|
Ok(RpcMessage::GameState(get_game()?.concede(self.account.id)?)),
|
|
|
|
RpcRequest::GameOfferDraw { game_id: _ } =>
|
|
Ok(RpcMessage::GameState(get_game()?.offer_draw(self.account.id)?)),
|
|
|
|
_ => Err(format_err!("unhandled anonymous request request={:?}", v)),
|
|
}
|
|
},
|
|
Err(e) => {
|
|
warn!("{:?}", e);
|
|
Err(err_msg("invalid message"))
|
|
},
|
|
}
|
|
}
|
|
}
|