rework rpc

This commit is contained in:
ntr 2018-10-08 23:26:28 +11:00
parent c950a0a866
commit 4d862a7900
7 changed files with 165 additions and 134 deletions

View File

@ -33,7 +33,6 @@ function CrypPanel({ cryps, sendCombatPve }) {
<div> <div>
<a className="button is-large is-fullwidth"> <a className="button is-large is-fullwidth">
<span>Spawn 👾</span> <span>Spawn 👾</span>
<span className="icon is-medium"><i className="fab fa-plus"></i></span>
</a> </a>
{crypPanels} {crypPanels}
</div> </div>

View File

@ -26,6 +26,7 @@ store.subscribe(() => console.log(store.getState()));
const ws = createSocket(store); const ws = createSocket(store);
store.dispatch(actions.setWs(ws)); store.dispatch(actions.setWs(ws));
ws.connect();
// tells jdenticon to look for new svgs and render them // tells jdenticon to look for new svgs and render them
// so we don't have to setInnerHtml or manually call update // so we don't have to setInnerHtml or manually call update

View File

@ -16,8 +16,34 @@ function errorToast(err) {
// requires the redux store in order to push updates // requires the redux store in order to push updates
// to components // to components
function createSocket(store) { function createSocket(store) {
const ws = new WebSocket('ws://localhost:40000'); let ws;
ws.binaryType = 'arraybuffer';
function connect() {
ws = new WebSocket('ws://localhost:40000');
ws.binaryType = 'arraybuffer';
// Connection opened
ws.addEventListener('open', function wsOpen(event) {
send({ method: 'account_login', params: { name: 'ntr', password: 'grepgrepgrep' } });
});
// Listen for messages
ws.addEventListener('message', onMessage);
ws.addEventListener('error', function wsError(event) {
console.error('WebSocket error', event);
account = null;
// return setTimeout(connect, 5000);
});
ws.addEventListener('close', function wsClose(event) {
console.error('WebSocket closed', event);
account = null;
return setTimeout(connect, 5000);
});
return ws;
}
// handle account auth within the socket itself // handle account auth within the socket itself
// https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html // https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html
@ -103,27 +129,10 @@ function createSocket(store) {
return handlers[method](params); return handlers[method](params);
} }
// Connection opened
ws.addEventListener('open', function wsOpen(event) {
send({ method: 'account_login', params: { name: 'ntr', password: 'grepgrepgrep' } });
});
// Listen for messages
ws.addEventListener('message', onMessage);
ws.addEventListener('error', function wsError(event) {
console.error('WebSocket error', event);
account = null;
});
ws.addEventListener('close', function wsClose(event) {
console.error('WebSocket closed', event);
account = null;
});
return { return {
sendAccountLogin, sendAccountLogin,
sendCombatPve, sendCombatPve,
connect,
}; };
} }

View File

@ -1,7 +1,7 @@
* Battling * Battling
* QOL * QOL
* auto login * auto login
* ws reconnect * ws reconnect ✔️
* Levelling * Levelling
* Global rolls * Global rolls
* Logins ✔️ * Logins ✔️

View File

@ -1,4 +1,4 @@
// use uuid::Uuid; use uuid::Uuid;
// use rand::prelude::*; // use rand::prelude::*;
use cryp::Cryp; use cryp::Cryp;
@ -14,48 +14,55 @@ use cryp::Cryp;
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Battle { pub struct Battle {
pub a: Cryp, pub a: Cryp,
pub b: Cryp, pub b: Cryp,
} }
impl Battle { impl Battle {
pub fn new(a: &Cryp, b: &Cryp) -> Battle { pub fn new(a: &Cryp, b: &Cryp) -> Battle {
return Battle { return Battle {
a: a.clone(), a: a.clone(),
b: b.clone(), b: b.clone(),
}; };
}
pub fn cryps(&self) -> Vec<&Cryp> {
vec![&self.a, &self.b]
}
pub fn next(&mut self) -> &mut Battle {
if self.finished() {
panic!("{:?} is finished", self);
} }
let a_turn = self.a.turn(); pub fn cryps(&self) -> Vec<&Cryp> {
let b_turn = self.b.turn(); vec![&self.a, &self.b]
self.a.assign_dmg(&self.b, &a_turn, &b_turn);
self.b.assign_dmg(&self.a, &b_turn, &a_turn);
self
}
pub fn finished(&self) -> bool {
self.cryps().iter().any(|c| c.is_ko())
}
pub fn winner(&self) -> Option<&Cryp> {
if self.cryps().iter().all(|c| c.is_ko()) {
return None
} }
match self.cryps().iter().find(|c| !c.is_ko()) { pub fn next(&mut self) -> &mut Battle {
Some(w) => Some(w), if self.finished() {
None => panic!("no winner found {:?}", self), panic!("{:?} is finished", self);
}
let a_turn = self.a.turn();
let b_turn = self.b.turn();
self.a.assign_dmg(&self.b, &a_turn, &b_turn);
self.b.assign_dmg(&self.a, &b_turn, &a_turn);
self
}
pub fn finished(&self) -> bool {
self.cryps().iter().any(|c| c.is_ko())
}
pub fn cryp_by_id(&self, id: Uuid) -> &Cryp {
match self.cryps().iter().find(|c| c.id == id) {
Some(c) => c,
None => panic!("cryp not in battle {:?}", self),
}
}
pub fn winner(&self) -> Option<&Cryp> {
if self.cryps().iter().all(|c| c.is_ko()) {
return None
}
match self.cryps().iter().find(|c| !c.is_ko()) {
Some(w) => Some(w),
None => panic!("no winner found {:?}", self),
}
} }
}
} }

View File

@ -1,6 +1,7 @@
use ws::{Sender}; use std::{thread, time};
use rand::prelude::*; use rand::prelude::*;
use serde_cbor::{from_slice, to_vec}; use serde_cbor::{from_slice};
// Db Commons // Db Commons
use failure::Error; use failure::Error;
@ -113,29 +114,32 @@ where F: Fn(&Battle) -> Result<(), Error>
// tells from_slice to cast into a cryp // tells from_slice to cast into a cryp
let cryp_bytes: Vec<u8> = returned.get("data"); let cryp_bytes: Vec<u8> = returned.get("data");
let mut plr: Cryp = from_slice::<Cryp>(&cryp_bytes)?; let plr: Cryp = from_slice::<Cryp>(&cryp_bytes)?;
let mob = generate_mob(&plr); let mob = generate_mob(&plr);
let mut battle = Battle::new(&plr, &mob); let mut battle = Battle::new(&plr, &mob);
loop { loop {
battle.next(); battle.next();
send(&battle)?; send(&battle)?;
if battle.finished() { if battle.finished() {
let success = match battle.winner() { let success = match battle.winner() {
Some(c) => c.id == plr.id, Some(c) => c.id == plr.id,
None => false, None => false,
}; };
let mut post_battle_plr = battle.cryp_by_id(plr.id).clone();
if success { if success {
plr = plr.add_xp(); post_battle_plr = post_battle_plr.add_xp();
write_cryp(plr, db, account)?;
} }
write_cryp(post_battle_plr, db, account)?;
break Ok(battle) break Ok(battle)
} }
} }
} }

View File

@ -31,79 +31,90 @@ impl Rpc {
// now we have the method name // now we have the method name
// match on that to determine what fn to call // match on that to determine what fn to call
match v.method.as_ref() { match v.method.as_ref() {
"cryp_spawn" => { "cryp_spawn" => Rpc::cryp_spawn(data, db, account),
match from_slice::<CrypSpawnMsg>(&data) { "combat_pve" => Rpc::combat_pve(data, db, account, out),
Ok(v) => { "account_create" => Rpc::account_create(data, db),
match account { "account_login" => Rpc::account_login(data, db),
Some(u) => Ok(RpcResponse { "account_cryps" => Rpc::account_cryps(db, account),
method: v.method,
params: RpcResult::SpawnCryp(spawn(v.params, db, u)?)
}),
None => Err(err_msg("auth required")),
}
}
Err(_e) => Err(err_msg("invalid params")),
}
},
"combat_pve" => {
let send = |b: &Battle| -> Result<(), Error> {
let reply = RpcResponse {
method: "battle_state".to_string(),
params: RpcResult::Pve(b.clone())
};
let response = to_vec(&reply)?;
match out.send(response) {
Ok(()) => Ok(()),
Err(e) => Err(err_msg(e))
}
};
match from_slice::<CombatPveMsg>(&data) {
Ok(v) => {
match account {
Some(u) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Pve(pve(v.params, db, u, send)?)
}),
None => Err(err_msg("auth required")),
}
}
Err(_e) => Err(err_msg("invalid params")),
}
},
"account_create" => {
match from_slice::<AccountCreateMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(create(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
},
"account_login" => {
match from_slice::<AccountLoginMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(login(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
},
"account_cryps" => {
match account {
Some(u) => Ok(RpcResponse {
method: v.method,
params: RpcResult::CrypList(fetch_cryps(db, u)?)
}),
None => Err(err_msg("auth required")),
}
},
_ => Err(err_msg("unknown method")), _ => Err(err_msg("unknown method")),
} }
}, },
Err(_e) => Err(err_msg("invalid message")), Err(_e) => Err(err_msg("invalid message")),
} }
} }
fn combat_pve(data: Vec<u8>, db: Db, account: Option<Account>, out: &Sender) -> Result<RpcResponse, Error> {
let send = |b: &Battle| -> Result<(), Error> {
let reply = RpcResponse {
method: "battle_state".to_string(),
params: RpcResult::Pve(b.clone())
};
let response = to_vec(&reply)?;
match out.send(response) {
Ok(()) => Ok(()),
Err(e) => Err(err_msg(e))
}
};
match from_slice::<CombatPveMsg>(&data) {
Ok(v) => {
match account {
Some(u) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Pve(pve(v.params, db, u, send)?)
}),
None => Err(err_msg("auth required")),
}
}
Err(_e) => Err(err_msg("invalid params")),
}
}
fn cryp_spawn(data: Vec<u8>, db: Db, account: Option<Account>) -> Result<RpcResponse, Error> {
match from_slice::<CrypSpawnMsg>(&data) {
Ok(v) => {
match account {
Some(u) => Ok(RpcResponse {
method: v.method,
params: RpcResult::SpawnCryp(spawn(v.params, db, u)?)
}),
None => Err(err_msg("auth required")),
}
}
Err(_e) => Err(err_msg("invalid params")),
}
}
fn account_create(data: Vec<u8>, db: Db) -> Result<RpcResponse, Error> {
match from_slice::<AccountCreateMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(create(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
}
fn account_login(data: Vec<u8>, db: Db) -> Result<RpcResponse, Error> {
match from_slice::<AccountLoginMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(login(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
}
fn account_cryps(db: Db, account: Option<Account>) -> Result<RpcResponse, Error> {
match account {
Some(u) => Ok(RpcResponse {
method: "account_cryps".to_string(),
params: RpcResult::CrypList(fetch_cryps(db, u)?)
}),
None => Err(err_msg("auth required")),
}
}
} }
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]