This commit is contained in:
ntr 2019-06-12 23:33:46 +10:00
parent a12e0c698f
commit 59320da37d
6 changed files with 536 additions and 427 deletions

View File

@ -29,6 +29,13 @@
*$$$*
clicks buy
creates stripe order / fill 0x order
server notified of payment
txs <- payment
buy supporter pack
account credited with features
char sets

View File

@ -1,7 +1,7 @@
const toast = require('izitoast');
const cbor = require('borc');
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/ws' : 'ws://localhost:40000';
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/ws' : 'ws://localhost:40000/ws/';
function errorToast(err) {
console.error(err);

View File

@ -25,3 +25,9 @@ failure = "0.1"
log = "0.4"
fern = "0.5"
actix = "0.8.2"
actix-web = "1.0.0"
actix-web-actors = "1.0.0"
futures = "0.1"
bytes = "0.4"

View File

@ -9,6 +9,10 @@ extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate actix;
extern crate actix_web;
extern crate actix_web_actors;
extern crate serde;
extern crate serde_cbor;
#[macro_use] extern crate serde_derive;

View File

@ -1,49 +1,122 @@
use failure::{Error, err_msg};
use tungstenite::Message;
use tungstenite::protocol::WebSocket;
use tungstenite::server::accept;
use tungstenite::Message::Binary;
use std::net::{TcpListener, TcpStream};
use std::time::{Instant, Duration};
use std::env;
use serde_cbor::{to_vec};
use std::env;
use std::thread::{spawn, sleep};
use std::time::{Instant, Duration};
use actix::prelude::*;
use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
use actix_web_actors::ws;
use r2d2::{Pool};
use r2d2::{PooledConnection};
use r2d2_postgres::{TlsMode, PostgresConnectionManager};
static DB_POOL_SIZE: u32 = 20;
pub type Db = PooledConnection<PostgresConnectionManager>;
use rpc::{Rpc};
use rpc::{receive, RpcErrorResponse};
use warden::{warden};
#[derive(Debug,Clone,Serialize,Deserialize)]
struct RpcErrorResponse {
err: String
pub type Db = PooledConnection<PostgresConnectionManager>;
type PgPool = Pool<PostgresConnectionManager>;
const DB_POOL_SIZE: u32 = 20;
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
/// websocket connection is long running connection, it easier
/// to handle with an actor
pub struct MnmlSocket {
/// Client must send ping at least once per 10 seconds (CLIENT_TIMEOUT),
/// otherwise we drop connection.
hb: Instant,
pool: PgPool,
}
fn receive(db: Db, begin: Instant, rpc: &Rpc, msg: Message, client: &mut WebSocket<TcpStream>) -> Result<String, Error> {
match rpc.receive(msg, begin, &db, client) {
impl Actor for MnmlSocket {
type Context = ws::WebsocketContext<Self>;
// once the actor has been started this fn runs
// it starts the heartbeat interval and keepalive
fn started(&mut self, ctx: &mut Self::Context) {
self.hb(ctx);
}
}
/// Handler for `ws::Message`
impl StreamHandler<ws::Message, ws::ProtocolError> for MnmlSocket {
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
// process websocket messages
println!("msg: {:?}", msg);
match msg {
ws::Message::Ping(msg) => {
self.hb = Instant::now();
ctx.pong(&msg);
}
ws::Message::Pong(_) => {
self.hb = Instant::now();
}
ws::Message::Text(text) => (),
ws::Message::Close(_) => {
ctx.stop();
}
ws::Message::Nop => (),
ws::Message::Binary(bin) => {
let db_connection = self.pool.get().expect("unable to get db connection");
match receive(bin.to_vec(), &db_connection, ctx) {
Ok(reply) => {
let response = to_vec(&reply)
.expect("failed to serialize response");
client.write_message(Binary(response))?;
return Ok(reply.method);
ctx.binary(response);
},
Err(e) => {
let response = to_vec(&RpcErrorResponse { err: e.to_string() })
.expect("failed to serialize error response");
client.write_message(Binary(response))?;
return Err(err_msg(e));
ctx.binary(response);
}
}
}
}
}
}
pub fn db_connection(url: String) -> Pool<PostgresConnectionManager> {
impl MnmlSocket {
fn new(state: web::Data<State>) -> MnmlSocket {
// idk why this has to be cloned again
// i guess because each socket is added as a new thread?
MnmlSocket { hb: Instant::now(), pool: state.pool.clone() }
}
// starts the keepalive interval once actor started
fn hb(&self, ctx: &mut <MnmlSocket as Actor>::Context) {
ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
info!("Websocket Client heartbeat failed, disconnecting!");
// stop actor
ctx.stop();
// don't try to send a ping
return;
}
ctx.ping("");
});
}
}
// idk how this stuff works
// but the args extract what you need from the incoming requests
// this grabs
// the req obj itself which we need for cookies
// the application state
// and the websocket stream
fn ws_index(r: HttpRequest, state: web::Data<State>, stream: web::Payload) -> Result<HttpResponse, Error> {
let res = ws::start(MnmlSocket::new(state), &r, stream);
// response of upgrade being sent back
// info!("res={:?}", res.as_ref().unwrap());
res
}
fn create_pool(url: String) -> Pool<PostgresConnectionManager> {
let manager = PostgresConnectionManager::new(url, TlsMode::None)
.expect("could not instantiate pg manager");
@ -53,76 +126,114 @@ pub fn db_connection(url: String) -> Pool<PostgresConnectionManager> {
.expect("Failed to create pool.")
}
// fn print_panic_payload(ctx: &str, payload: &(Any + Send + 'static)) {
// let d = format!("{:?}", payload);
// let s = if let Some(s) = payload.downcast_ref::<String>() {
// &s
// } else if let Some(s) = payload.downcast_ref::<&str>() {
// s
// } else {
// // "PAYLOAD IS NOT A STRING"
// d.as_str()
// };
// info!("{}: PANIC OCCURRED: {}", ctx, s);
// }
// This struct represents state
struct State {
pool: PgPool,
}
pub fn start() {
// panic::set_hook(Box::new(|panic_info| {
// print_panic_payload("set_hook", panic_info.payload());
// if let Some(location) = panic_info.location() {
// info!("LOCATION: {}:{}", location.file(), location.line());
// } else {
// info!("NO LOCATION INFORMATION");
// }
// }));
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let pool = db_connection(database_url);
let pool = create_pool(database_url);
// {
// let startup_connection = pool.get().expect("unable to get db connection");
// startup(startup_connection).unwrap();
// }
let server = TcpListener::bind("0.0.0.0:40000").unwrap();
let warden_pool = pool.clone();
spawn(move || {
loop {
let db_connection = warden_pool.get().expect("unable to get db connection");
if let Err(e) = warden(db_connection) {
info!("{:?}", e);
}
sleep(Duration::new(1, 0));
}
});
for stream in server.incoming() {
let db = pool.clone();
spawn(move || {
let mut websocket = accept(stream.unwrap()).unwrap();
let rpc = Rpc {};
loop {
match websocket.read_message() {
Ok(msg) => {
let begin = Instant::now();
let db_connection = db.get().expect("unable to get db connection");
match receive(db_connection, begin, &rpc, msg, &mut websocket) {
Ok(_) => (),
Err(e) => warn!("{:?}", e),
}
},
// connection is closed
Err(e) => {
debug!("{:?}", e);
return;
}
};
}
});
}
HttpServer::new(move || {
App::new()
.data(State { pool: pool.clone() })
// enable logger
.wrap(middleware::Logger::default())
// websocket route
.service(web::resource("/ws/").route(web::get().to(ws_index)))
})
.bind("127.0.0.1:40000").expect("could not bind to port")
.run().expect("could not start http server");
}
// #[derive(Debug,Clone,Serialize,Deserialize)]
// struct RpcErrorResponse {
// err: String
// }
// pub fn db_connection(url: String) -> Pool<PostgresConnectionManager> {
// let manager = PostgresConnectionManager::new(url, TlsMode::None)
// .expect("could not instantiate pg manager");
// Pool::builder()
// .max_size(DB_POOL_SIZE)
// .build(manager)
// .expect("Failed to create pool.")
// }
// // fn print_panic_payload(ctx: &str, payload: &(Any + Send + 'static)) {
// // let d = format!("{:?}", payload);
// // let s = if let Some(s) = payload.downcast_ref::<String>() {
// // &s
// // } else if let Some(s) = payload.downcast_ref::<&str>() {
// // s
// // } else {
// // // "PAYLOAD IS NOT A STRING"
// // d.as_str()
// // };
// // info!("{}: PANIC OCCURRED: {}", ctx, s);
// // }
// pub fn start() {
// // panic::set_hook(Box::new(|panic_info| {
// // print_panic_payload("set_hook", panic_info.payload());
// // if let Some(location) = panic_info.location() {
// // info!("LOCATION: {}:{}", location.file(), location.line());
// // } else {
// // info!("NO LOCATION INFORMATION");
// // }
// // }));
// let database_url = env::var("DATABASE_URL")
// .expect("DATABASE_URL must be set");
// let pool = db_connection(database_url);
// // {
// // let startup_connection = pool.get().expect("unable to get db connection");
// // startup(startup_connection).unwrap();
// // }
// let server = TcpListener::bind("0.0.0.0:40000").unwrap();
// let warden_pool = pool.clone();
// spawn(move || {
// loop {
// let db_connection = warden_pool.get().expect("unable to get db connection");
// if let Err(e) = warden(db_connection) {
// info!("{:?}", e);
// }
// sleep(Duration::new(1, 0));
// }
// });
// for stream in server.incoming() {
// let db = pool.clone();
// spawn(move || {
// let mut websocket = accept(stream.unwrap()).unwrap();
// let rpc = Rpc {};
// loop {
// match websocket.read_message() {
// Ok(msg) => {
// let begin = Instant::now();
// let db_connection = db.get().expect("unable to get db connection");
// match receive(db_connection, begin, &rpc, msg, &mut websocket) {
// Ok(_) => (),
// Err(e) => warn!("{:?}", e),
// }
// },
// // connection is closed
// Err(e) => {
// debug!("{:?}", e);
// return;
// }
// };
// }
// });
// }
// }

View File

@ -1,17 +1,12 @@
use tungstenite::Message;
use tungstenite::protocol::WebSocket;
use tungstenite::Message::Binary;
use actix_web_actors::ws;
use postgres::transaction::Transaction;
use std::net::{TcpStream};
use std::time::Instant;
use serde_cbor::{from_slice, to_vec};
use uuid::Uuid;
use failure::Error;
use failure::err_msg;
use net::Db;
use net::{Db, MnmlSocket};
use construct::{Construct, construct_spawn, construct_delete};
use game::{Game, game_state, game_skill, game_ready};
use account::{Account, account_create, account_login, account_from_token, account_constructs, account_instances};
@ -20,14 +15,11 @@ use instance::{Instance, instance_state, instance_list, instance_new, instance_r
use vbox::{vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
use item::{Item, ItemInfoCtr, item_info};
pub struct Rpc;
impl Rpc {
pub fn receive(&self, msg: Message, begin: Instant, db: &Db, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
// consume the ws data into bytes
let data = msg.into_data();
type MnmlWs = ws::WebsocketContext<MnmlSocket>;
// cast the msg to this type to receive method name
pub fn receive(data: Vec<u8>, db: &Db, client: &mut MnmlWs) -> Result<RpcResponse, Error> {
// cast the data to this type to receive method name
match from_slice::<RpcMessage>(&data) {
Ok(v) => {
if v.method == "ping" {
@ -62,41 +54,39 @@ impl Rpc {
// match on that to determine what fn to call
let response = match v.method.as_ref() {
// NO AUTH
"account_create" => Rpc::account_create(data, &mut tx, client),
"account_login" => Rpc::account_login(data, &mut tx, client),
"account_create" => handle_account_create(data, &mut tx, client),
"account_login" => handle_account_login(data, &mut tx, client),
"item_info" => Ok(RpcResponse { method: "item_info".to_string(), params: RpcResult::ItemInfo(item_info()) }),
// AUTH METHODS
"account_constructs" => Rpc::account_constructs(data, &mut tx, account.unwrap(), client),
"account_instances" => Rpc::account_instances(data, &mut tx, account.unwrap(), client),
"account_constructs" => handle_account_constructs(data, &mut tx, account.unwrap(), client),
"account_instances" => handle_account_instances(data, &mut tx, account.unwrap(), client),
"construct_spawn" => Rpc::construct_spawn(data, &mut tx, account.unwrap(), client),
"construct_delete" => Rpc::construct_delete(data, &mut tx, account.unwrap(), client),
"construct_spawn" => handle_construct_spawn(data, &mut tx, account.unwrap(), client),
"construct_delete" => handle_construct_delete(data, &mut tx, account.unwrap(), client),
"game_state" => Rpc::game_state(data, &mut tx, account.unwrap(), client),
"game_skill" => Rpc::game_skill(data, &mut tx, account.unwrap(), client),
"game_ready" => Rpc::game_ready(data, &mut tx, account.unwrap(), client),
"game_state" => handle_game_state(data, &mut tx, account.unwrap(), client),
"game_skill" => handle_game_skill(data, &mut tx, account.unwrap(), client),
"game_ready" => handle_game_ready(data, &mut tx, account.unwrap(), client),
"instance_list" => Rpc::instance_list(data, &mut tx, account.unwrap(), client),
"instance_join" => Rpc::instance_join(data, &mut tx, account.unwrap(), client),
"instance_ready" => Rpc::instance_ready(data, &mut tx, account.unwrap(), client),
"instance_new" => Rpc::instance_new(data, &mut tx, account.unwrap(), client),
"instance_state" => Rpc::instance_state(data, &mut tx, account.unwrap(), client),
"instance_list" => handle_instance_list(data, &mut tx, account.unwrap(), client),
"instance_join" => handle_instance_join(data, &mut tx, account.unwrap(), client),
"instance_ready" => handle_instance_ready(data, &mut tx, account.unwrap(), client),
"instance_new" => handle_instance_new(data, &mut tx, account.unwrap(), client),
"instance_state" => handle_instance_state(data, &mut tx, account.unwrap(), client),
"vbox_accept" => Rpc::vbox_accept(data, &mut tx, account.unwrap(), client),
"vbox_apply" => Rpc::vbox_apply(data, &mut tx, account.unwrap(), client),
"vbox_combine" => Rpc::vbox_combine(data, &mut tx, account.unwrap(), client),
"vbox_discard" => Rpc::vbox_discard(data, &mut tx, account.unwrap(), client),
"vbox_reclaim" => Rpc::vbox_reclaim(data, &mut tx, account.unwrap(), client),
"vbox_unequip" => Rpc::vbox_unequip(data, &mut tx, account.unwrap(), client),
"vbox_accept" => handle_vbox_accept(data, &mut tx, account.unwrap(), client),
"vbox_apply" => handle_vbox_apply(data, &mut tx, account.unwrap(), client),
"vbox_combine" => handle_vbox_combine(data, &mut tx, account.unwrap(), client),
"vbox_discard" => handle_vbox_discard(data, &mut tx, account.unwrap(), client),
"vbox_reclaim" => handle_vbox_reclaim(data, &mut tx, account.unwrap(), client),
"vbox_unequip" => handle_vbox_unequip(data, &mut tx, account.unwrap(), client),
_ => Err(format_err!("unknown method - {:?}", v.method)),
};
tx.commit()?;
info!("method={:?} account={:?} duration={:?}", v.method, account_name, begin.elapsed());
return response;
},
Err(e) => {
@ -104,17 +94,9 @@ impl Rpc {
Err(err_msg("unknown error"))
},
}
}
}
fn send_msg(client: &mut WebSocket<TcpStream>, msg: RpcResponse) -> Result<(), Error> {
let bytes = to_vec(&msg)?;
match client.write_message(Binary(bytes)) {
Ok(()) => Ok(()),
Err(e) => Err(err_msg(e))
}
}
fn game_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_game_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<GameStateMsg>(&data).or(Err(err_msg("invalid params")))?;
let game_response = RpcResponse {
@ -123,20 +105,20 @@ impl Rpc {
};
return Ok(game_response);
}
}
// fn game_pve(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
// let msg = from_slice::<GamePveMsg>(&data).or(Err(err_msg("invalid params")))?;
// fn handle_game_pve(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
// let msg = from_slice::<GamePveMsg>(&data).or(Err(err_msg("invalid params")))?;
// let game_response = RpcResponse {
// method: "game_state".to_string(),
// params: RpcResult::GameState(game_pve(msg.params, tx, &account)?)
// };
// let game_response = RpcResponse {
// method: "game_state".to_string(),
// params: RpcResult::GameState(game_pve(msg.params, tx, &account)?)
// };
// return Ok(game_response);
// }
// return Ok(game_response);
// }
fn game_skill(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_game_skill(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<GameSkillMsg>(&data).or(Err(err_msg("invalid params")))?;
let game_response = RpcResponse {
@ -145,9 +127,9 @@ impl Rpc {
};
return Ok(game_response);
}
}
fn game_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_game_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<GameStateMsg>(&data).or(Err(err_msg("invalid params")))?;
let game_response = RpcResponse {
@ -156,26 +138,21 @@ impl Rpc {
};
return Ok(game_response);
}
}
fn construct_spawn(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_construct_spawn(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<ConstructSpawnMsg>(&data).or(Err(err_msg("invalid params")))?;
Rpc::send_msg(client, RpcResponse {
method: "construct_spawn".to_string(),
params: RpcResult::ConstructSpawn(construct_spawn(msg.params, tx, &account)?)
})?;
let construct_list = RpcResponse {
method: "account_constructs".to_string(),
params: RpcResult::ConstructList(account_constructs(tx, &account)?)
};
Ok(construct_list)
}
}
fn construct_delete(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_construct_delete(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<ConstructDeleteMsg>(&data).or(Err(err_msg("invalid params")))?;
construct_delete(tx, msg.params.id, account.id)?;
@ -186,10 +163,10 @@ impl Rpc {
};
Ok(construct_list)
}
}
fn account_create(data: Vec<u8>, tx: &mut Transaction, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_account_create(data: Vec<u8>, tx: &mut Transaction, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<AccountCreateMsg>(&data).or(Err(err_msg("invalid params")))?;
let account = account_create(msg.params, tx)?;
@ -198,9 +175,9 @@ impl Rpc {
method: "account_create".to_string(),
params: RpcResult::Account(account)
})
}
}
fn account_login(data: Vec<u8>, tx: &mut Transaction, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_account_login(data: Vec<u8>, tx: &mut Transaction, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
match from_slice::<AccountLoginMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
@ -208,48 +185,48 @@ impl Rpc {
}),
Err(_e) => Err(err_msg("invalid params")),
}
}
}
// fn account_demo(_data: Vec<u8>, tx: &mut Transaction, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
// let mut rng = thread_rng();
// fn handle_account_demo(_data: Vec<u8>, tx: &mut Transaction, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
// let mut rng = thread_rng();
// let acc_name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// let acc_name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// let account = account_create(AccountCreateParams { name: acc_name, password: "grepgrepgrep".to_string() }, tx)?;
// let account = account_create(AccountCreateParams { name: acc_name, password: "grepgrepgrep".to_string() }, tx)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
// construct_spawn(ConstructSpawnParams { name }, tx, &account)?;
// let res = RpcResponse {
// method: "account_create".to_string(),
// params: RpcResult::Account(account),
// };
// let res = RpcResponse {
// method: "account_create".to_string(),
// params: RpcResult::Account(account),
// };
// return Ok(res);
// }
// return Ok(res);
// }
fn account_constructs(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_account_constructs(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
Ok(RpcResponse {
method: "account_constructs".to_string(),
params: RpcResult::ConstructList(account_constructs(tx, &account)?)
})
}
}
fn account_instances(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_account_instances(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
Ok(RpcResponse {
method: "account_instances".to_string(),
params: RpcResult::InstanceList(account_instances(tx, &account)?)
})
}
}
fn instance_new(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_instance_new(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceLobbyMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -258,9 +235,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn instance_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_instance_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceReadyMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -269,9 +246,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn instance_join(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_instance_join(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceJoinMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -280,30 +257,30 @@ impl Rpc {
};
return Ok(response);
}
}
fn instance_list(_data: Vec<u8>, tx: &mut Transaction, _account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_instance_list(_data: Vec<u8>, tx: &mut Transaction, _account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let response = RpcResponse {
method: "instance_list".to_string(),
params: RpcResult::InstanceList(instance_list(tx)?)
};
return Ok(response);
}
}
// fn instance_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
// let msg = from_slice::<InstanceReadyMsg>(&data).or(Err(err_msg("invalid params")))?;
// fn handle_instance_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
// let msg = from_slice::<InstanceReadyMsg>(&data).or(Err(err_msg("invalid params")))?;
// let response = RpcResponse {
// method: "game_state".to_string(),
// params: RpcResult::GameState(instance_ready(msg.params, tx, &account)?)
// };
// let response = RpcResponse {
// method: "game_state".to_string(),
// params: RpcResult::GameState(instance_ready(msg.params, tx, &account)?)
// };
// return Ok(response);
// }
// return Ok(response);
// }
fn instance_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_instance_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<InstanceStateMsg>(&data).or(Err(err_msg("invalid params")))?;
match instance_state(msg.params, tx, &account)? {
RpcResult::GameState(p) => Ok(RpcResponse {
@ -316,9 +293,9 @@ impl Rpc {
}),
_ => Err(err_msg("unhandled instance state"))
}
}
}
fn vbox_accept(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_accept(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxAcceptMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -327,9 +304,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn vbox_discard(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_discard(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxDiscardMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -338,10 +315,10 @@ impl Rpc {
};
return Ok(response);
}
}
fn vbox_combine(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_combine(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxCombineMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -350,9 +327,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn vbox_apply(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_apply(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxApplyMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -361,9 +338,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn vbox_reclaim(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_reclaim(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxReclaimMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -372,9 +349,9 @@ impl Rpc {
};
return Ok(response);
}
}
fn vbox_unequip(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
fn handle_vbox_unequip(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut MnmlWs) -> Result<RpcResponse, Error> {
let msg = from_slice::<VboxUnequipMsg>(&data).or(Err(err_msg("invalid params")))?;
let response = RpcResponse {
@ -383,7 +360,11 @@ impl Rpc {
};
return Ok(response);
}
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct RpcErrorResponse {
pub err: String
}
#[derive(Debug,Clone,Serialize,Deserialize)]