use std::time::{Instant}; use actix_web_actors::ws; use serde_cbor::{from_slice}; use uuid::Uuid; use failure::Error; use failure::err_msg; use net::{Db}; use ws::{MnmlSocket}; 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; type MnmlWs = ws::WebsocketContext; #[derive(Debug,Clone,Serialize,Deserialize)] pub enum RpcResult { AccountState(Account), AccountConstructs(Vec), AccountInstances(Vec), 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 }, MtxAccountApply { mtx: mtx::MtxVariant }, GameState { id: Uuid }, GameReady { id: Uuid }, GameSkill { game_id: Uuid, construct_id: Uuid, target_construct_id: Option, skill: Skill }, AccountState {}, AccountConstructs {}, AccountInstances {}, 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 MnmlWs, begin: Instant, account: Option<&Account>) -> 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(RpcResult::Pong(())), RpcRequest::ItemInfo {} => return Ok(RpcResult::ItemInfo(item_info())), RpcRequest::DevResolve {a, b, skill } => return Ok(RpcResult::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(RpcResult::AccountState(account.clone())), RpcRequest::AccountConstructs {} => Ok(RpcResult::AccountConstructs(account_constructs(&mut tx, &account)?)), RpcRequest::AccountInstances {} => Ok(RpcResult::AccountInstances(account_instances(&mut tx, &account)?)), // RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account), RpcRequest::GameState { id } => Ok(RpcResult::GameState(game_state(&mut tx, account, id)?)), RpcRequest::GameSkill { game_id, construct_id, target_construct_id, skill } => Ok(RpcResult::GameState(game_skill(&mut tx, account, game_id, construct_id, target_construct_id, skill)?)), RpcRequest::GameReady { id } => Ok(RpcResult::GameState(game_ready(&mut tx, account, id)?)), RpcRequest::InstanceList {} => Ok(RpcResult::OpenInstances(instance_list(&mut tx)?)), RpcRequest::InstanceLobby { construct_ids, name, pve, password } => Ok(RpcResult::InstanceState(instance_new(&mut tx, account, construct_ids, name, pve, password)?)), RpcRequest::InstanceJoin { instance_id, construct_ids } => Ok(RpcResult::InstanceState(instance_join(&mut tx, account, instance_id, construct_ids)?)), RpcRequest::InstanceReady { instance_id } => Ok(RpcResult::InstanceState(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(RpcResult::InstanceState(vbox_accept(&mut tx, account, instance_id, group, index)?)), RpcRequest::VboxApply { instance_id, construct_id, index } => Ok(RpcResult::InstanceState(vbox_apply(&mut tx, account, instance_id, construct_id, index)?)), RpcRequest::VboxCombine { instance_id, indices } => Ok(RpcResult::InstanceState(vbox_combine(&mut tx, account, instance_id, indices)?)), RpcRequest::VboxDiscard { instance_id } => Ok(RpcResult::InstanceState(vbox_discard(&mut tx, account, instance_id)?)), RpcRequest::VboxReclaim { instance_id, index } => Ok(RpcResult::InstanceState(vbox_reclaim(&mut tx, account, instance_id, index)?)), RpcRequest::VboxUnequip { instance_id, construct_id, target } => Ok(RpcResult::InstanceState(vbox_unequip(&mut tx, account, instance_id, construct_id, target)?)), // "mtx_apply" => handle_mtx_apply(data, &mut tx, account), _ => Err(format_err!("unknown request request={:?}", request)), }; tx.commit()?; info!("request={:?} account={:?} duration={:?}", request, account.name, begin.elapsed()); return response; }, Err(e) => { info!("{:?}", e); Err(format_err!("invalid message data={:?}", data)) }, } } // fn handle_mtx_apply(data: Vec, tx: &mut Transaction, account: &Account) -> Result { // let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; // match msg.params { // MtxApplyParams::ConstructApply { construct_id, mtx } => // mtx::apply(tx, mtx, construct_id, account.id)?, // _ => unimplemented!(), // }; // Ok(RpcResult::AccountConstructs(account_constructs(tx, &account)?)) // }