From 4d862a79005a6318e53310f1323bcb7f616ac7c7 Mon Sep 17 00:00:00 2001 From: ntr Date: Mon, 8 Oct 2018 23:26:28 +1100 Subject: [PATCH] rework rpc --- client/src/components/cryp.list.jsx | 1 - client/src/main.jsx | 1 + client/src/socket.jsx | 49 ++++++---- server/WORKLOG.md | 2 +- server/src/battle.rs | 81 +++++++++------- server/src/combat.rs | 22 +++-- server/src/rpc.rs | 143 +++++++++++++++------------- 7 files changed, 165 insertions(+), 134 deletions(-) diff --git a/client/src/components/cryp.list.jsx b/client/src/components/cryp.list.jsx index 294fc6d0..a3b57604 100644 --- a/client/src/components/cryp.list.jsx +++ b/client/src/components/cryp.list.jsx @@ -33,7 +33,6 @@ function CrypPanel({ cryps, sendCombatPve }) {
Spawn 👾 - {crypPanels}
diff --git a/client/src/main.jsx b/client/src/main.jsx index 15b1bfb9..4e3c6505 100755 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -26,6 +26,7 @@ store.subscribe(() => console.log(store.getState())); const ws = createSocket(store); store.dispatch(actions.setWs(ws)); +ws.connect(); // tells jdenticon to look for new svgs and render them // so we don't have to setInnerHtml or manually call update diff --git a/client/src/socket.jsx b/client/src/socket.jsx index e8b9f199..62686db4 100644 --- a/client/src/socket.jsx +++ b/client/src/socket.jsx @@ -16,8 +16,34 @@ function errorToast(err) { // requires the redux store in order to push updates // to components function createSocket(store) { - const ws = new WebSocket('ws://localhost:40000'); - ws.binaryType = 'arraybuffer'; + let ws; + + 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 // https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html @@ -103,27 +129,10 @@ function createSocket(store) { 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 { sendAccountLogin, sendCombatPve, + connect, }; } diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 1ad4ff5b..3cd8e97c 100755 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -1,7 +1,7 @@ * Battling * QOL * auto login - * ws reconnect + * ws reconnect ✔️ * Levelling * Global rolls * Logins ✔️ diff --git a/server/src/battle.rs b/server/src/battle.rs index d190911d..ef9779ae 100755 --- a/server/src/battle.rs +++ b/server/src/battle.rs @@ -1,4 +1,4 @@ -// use uuid::Uuid; +use uuid::Uuid; // use rand::prelude::*; use cryp::Cryp; @@ -14,48 +14,55 @@ use cryp::Cryp; #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Battle { - pub a: Cryp, - pub b: Cryp, + pub a: Cryp, + pub b: Cryp, } impl Battle { - pub fn new(a: &Cryp, b: &Cryp) -> Battle { - return Battle { - a: a.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); + pub fn new(a: &Cryp, b: &Cryp) -> Battle { + return Battle { + a: a.clone(), + b: b.clone(), + }; } - 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 winner(&self) -> Option<&Cryp> { - if self.cryps().iter().all(|c| c.is_ko()) { - return None + pub fn cryps(&self) -> Vec<&Cryp> { + vec![&self.a, &self.b] } - match self.cryps().iter().find(|c| !c.is_ko()) { - Some(w) => Some(w), - None => panic!("no winner found {:?}", self), + pub fn next(&mut self) -> &mut Battle { + if self.finished() { + 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), + } } - } } diff --git a/server/src/combat.rs b/server/src/combat.rs index 1c4e7edf..8ce03fb4 100755 --- a/server/src/combat.rs +++ b/server/src/combat.rs @@ -1,6 +1,7 @@ -use ws::{Sender}; +use std::{thread, time}; + use rand::prelude::*; -use serde_cbor::{from_slice, to_vec}; +use serde_cbor::{from_slice}; // Db Commons use failure::Error; @@ -113,29 +114,32 @@ where F: Fn(&Battle) -> Result<(), Error> // tells from_slice to cast into a cryp let cryp_bytes: Vec = returned.get("data"); - let mut plr: Cryp = from_slice::(&cryp_bytes)?; + let plr: Cryp = from_slice::(&cryp_bytes)?; let mob = generate_mob(&plr); let mut battle = Battle::new(&plr, &mob); loop { - battle.next(); + battle.next(); - send(&battle)?; + send(&battle)?; - if battle.finished() { + if battle.finished() { let success = match battle.winner() { Some(c) => c.id == plr.id, None => false, }; + let mut post_battle_plr = battle.cryp_by_id(plr.id).clone(); + if success { - plr = plr.add_xp(); - write_cryp(plr, db, account)?; + post_battle_plr = post_battle_plr.add_xp(); } + write_cryp(post_battle_plr, db, account)?; + break Ok(battle) - } + } } } diff --git a/server/src/rpc.rs b/server/src/rpc.rs index 4feed4be..cad78566 100755 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -31,79 +31,90 @@ impl Rpc { // now we have the method name // match on that to determine what fn to call match v.method.as_ref() { - "cryp_spawn" => { - match from_slice::(&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")), - } - }, - "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)) - } - }; + "cryp_spawn" => Rpc::cryp_spawn(data, db, account), + "combat_pve" => Rpc::combat_pve(data, db, account, out), + "account_create" => Rpc::account_create(data, db), + "account_login" => Rpc::account_login(data, db), + "account_cryps" => Rpc::account_cryps(db, account), - match from_slice::(&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::(&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::(&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(_e) => Err(err_msg("invalid message")), } } + + fn combat_pve(data: Vec, db: Db, account: Option, out: &Sender) -> Result { + 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::(&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, db: Db, account: Option) -> Result { + match from_slice::(&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, db: Db) -> Result { + match from_slice::(&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, db: Db) -> Result { + match from_slice::(&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) -> Result { + 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)]