use std::net::TcpStream; use std::time::{Instant}; use serde_cbor::{from_slice}; use uuid::Uuid; use failure::Error; use failure::err_msg; use ws::{Ws}; use pg::{Db}; use construct::{Construct}; use game::{Game, game_state, game_skill, game_ready}; use account::{Account, account_constructs, account_instances}; use skill::{Skill, dev_resolve, Resolutions}; use instance::{Instance, instance_state, instance_list, instance_new, instance_ready, instance_join}; use vbox::{vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip}; use item::{Item, ItemInfoCtr, item_info}; use mtx; #[derive(Debug,Clone,Serialize,Deserialize)] pub enum RpcMessage { AccountState(Account), AccountConstructs(Vec), AccountInstances(Vec), AccountShop(mtx::Shop), GameState(Game), ItemInfo(ItemInfoCtr), OpenInstances(Vec), InstanceState(Instance), Pong(()), DevResolutions(Resolutions), } #[derive(Debug,Clone,Serialize,Deserialize)] enum RpcRequest { Ping {}, ItemInfo {}, DevResolve { a: Uuid, b: Uuid, skill: Skill }, MtxConstructApply { mtx: mtx::MtxVariant, construct_id: Uuid, name: String }, MtxAccountApply { mtx: mtx::MtxVariant }, MtxBuy { mtx: mtx::MtxVariant }, GameState { id: Uuid }, GameReady { id: Uuid }, GameSkill { game_id: Uuid, construct_id: Uuid, target_construct_id: Option, skill: Skill }, AccountState {}, AccountShop {}, AccountConstructs {}, InstanceList {}, InstanceLobby { construct_ids: Vec, name: String, pve: bool, password: Option }, InstanceJoin { instance_id: Uuid, construct_ids: Vec }, InstanceReady { instance_id: Uuid }, InstanceState { instance_id: Uuid }, VboxAccept { instance_id: Uuid, group: usize, index: usize }, VboxDiscard { instance_id: Uuid }, VboxCombine { instance_id: Uuid, indices: Vec }, VboxApply { instance_id: Uuid, construct_id: Uuid, index: usize }, VboxUnequip { instance_id: Uuid, construct_id: Uuid, target: Item }, VboxReclaim { instance_id: Uuid, index: usize }, } pub fn receive(data: Vec, db: &Db, _client: &mut Ws, begin: Instant, account: &Option) -> Result { // cast the msg to this type to receive method name match from_slice::(&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 {a, b, skill } => return Ok(RpcMessage::DevResolutions(dev_resolve(a, b, skill))), _ => (), }; // check for authorization now let account = match account { Some(account) => account, None => return Err(err_msg("auth required")), }; // all good, let's make a tx and process let mut tx = db.transaction()?; let request = v.clone(); let response = match v { RpcRequest::AccountState {} => return Ok(RpcMessage::AccountState(account.clone())), RpcRequest::AccountConstructs {} => Ok(RpcMessage::AccountConstructs(account_constructs(&mut tx, &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::GameReady { id } => Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)), RpcRequest::InstanceList {} => Ok(RpcMessage::OpenInstances(instance_list(&mut tx)?)), RpcRequest::InstanceLobby { construct_ids, name, pve, password } => Ok(RpcMessage::InstanceState(instance_new(&mut tx, account, construct_ids, name, pve, password)?)), RpcRequest::InstanceJoin { instance_id, construct_ids } => Ok(RpcMessage::InstanceState(instance_join(&mut tx, account, instance_id, construct_ids)?)), // 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, account, instance_id)?), RpcRequest::VboxAccept { instance_id, group, index } => Ok(RpcMessage::InstanceState(vbox_accept(&mut tx, account, instance_id, group, index)?)), RpcRequest::VboxApply { instance_id, construct_id, index } => Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, account, instance_id, construct_id, index)?)), RpcRequest::VboxCombine { instance_id, indices } => Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, account, instance_id, indices)?)), RpcRequest::VboxDiscard { instance_id } => Ok(RpcMessage::InstanceState(vbox_discard(&mut tx, account, instance_id)?)), RpcRequest::VboxReclaim { instance_id, index } => Ok(RpcMessage::InstanceState(vbox_reclaim(&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)?)), RpcRequest::MtxConstructApply { mtx, construct_id, name } => Ok(RpcMessage::AccountConstructs(mtx::apply(&mut tx, account, mtx, construct_id, name)?)), RpcRequest::MtxBuy { mtx } => Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)), _ => Err(format_err!("unknown request request={:?}", request)), }; tx.commit()?; info!("request={:?} account={:?} duration={:?}", request, account.name, begin.elapsed()); return response; }, Err(e) => { warn!("{:?}", e); Err(err_msg("invalid message")) }, } }