mnml/server/src/rpc.rs
2019-07-25 14:33:03 +10:00

171 lines
6.6 KiB
Rust

use std::net::TcpStream;
use std::time::{Instant};
use serde_cbor::{from_slice};
use uuid::Uuid;
use failure::Error;
use failure::err_msg;
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<Construct>),
AccountInstances(Vec<Instance>),
AccountShop(mtx::Shop),
GameState(Game),
ItemInfo(ItemInfoCtr),
OpenInstances(Vec<Instance>),
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<Uuid>, skill: Skill },
AccountState {},
AccountShop {},
AccountConstructs {},
InstanceList {},
InstanceLobby { construct_ids: Vec<Uuid>, name: String, pve: bool, password: Option<String> },
InstanceJoin { instance_id: Uuid, construct_ids: Vec<Uuid> },
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<usize> },
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<u8>, db: &Db, begin: Instant, account: &Option<Account>) -> 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 {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"))
},
}
}