This commit is contained in:
ntr 2018-09-23 22:01:20 +10:00
parent f825b26b37
commit d28d3df1ec
9 changed files with 140 additions and 43 deletions

View File

@ -1,10 +1,16 @@
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const InvStats = require('./invstats'); const CrypPanel = require('./cryp.panel');
// Add the incident from state as a property
const addState = connect( const addState = connect(
state => ({ cryp: state.cryp }) function receiveState(state) {
const { ws, cryp } = state;
function sendCombatPve() {
return ws.sendCombatPve(cryp.id);
}
return { cryp, sendCombatPve };
}
); );
module.exports = addState(InvStats); module.exports = addState(CrypPanel);

View File

@ -1,54 +1,60 @@
const preact = require('preact'); const preact = require('preact');
function InvStats({ cryp }) { function CrypPanel({ cryp, sendCombatPve }) {
if (!cryp) return <div>not ready</div>; if (!cryp) return <div>not ready</div>;
return ( return (
<div className="tile is-ancestor has-text-centered has-background-grey is-dark is-10"> <div className="tile is-ancestor has-text-centered has-background-grey is-dark is-10">
<div className="tile is-6"> <div className="tile is-6">
<div className="tile is-parent is-vertical is-3"> <div className="tile is-parent is-vertical is-3">
<article className="tile is-child notification is-success"> <section className="tile is-child notification is-success">
<p>Helm Slot</p> <p>Helm Slot</p>
</article> </section>
<article className="tile is-child notification is-success"> <section className="tile is-child notification is-success">
<p>Body Armor</p> <p>Body Armor</p>
</article> </section>
<article className="tile is-child notification is-success"> <section className="tile is-child notification is-success">
<p>Gloves</p> <p>Gloves</p>
</article> </section>
<article className="tile is-child notification is-success"> <section className="tile is-child notification is-success">
<p>Boots</p> <p>Boots</p>
</article> </section>
</div> </div>
<div className="tile is-parent is-6"> <div className="tile is-parent is-6">
<article className="tile is-child notification is-info"> <section className="tile is-child notification is-info">
<figure className="image"> <figure className="image">
<svg width="160" height="160" data-jdenticon-value={cryp.name} /> <svg width="160" height="160" data-jdenticon-value={cryp.name} />
</figure> </figure>
<p className="title">{cryp.name}</p> <p className="title">{cryp.name}</p>
<p className="subtitle">The big boy</p> <p className="subtitle">The big boy</p>
</article> </section>
</div> </div>
<div className="tile is-parent is-vertical is-3"> <div className="tile is-parent is-vertical is-3">
<article className="tile is-child notification is-dark"> <section className="tile is-child notification is-dark">
<p>Weapon</p> <p>Weapon</p>
</article> </section>
<article className="tile is-child notification is-dark"> <section className="tile is-child notification is-dark">
<p>Jewellery</p> <p>Jewellery</p>
</article> </section>
<article className="tile is-child notification is-dark"> <section className="tile is-child notification is-dark">
<p>Artifact</p> <p>Artifact</p>
</article> </section>
</div> </div>
</div> </div>
<div className="tile is-parent is-6"> <div className="tile is-parent is-6">
<article className="tile is-child notification has-background-grey is-dark"> <section className="tile is-child notification has-background-grey is-dark">
<p className="title">Stat Area</p> <p className="title">Stat Area</p>
<p>{JSON.stringify(cryp.def)}</p> <p>{JSON.stringify(cryp.def)}</p>
<p>{JSON.stringify(cryp.dmg)}</p> <p>{JSON.stringify(cryp.dmg)}</p>
<p>{JSON.stringify(cryp.hp)}</p> <p>{JSON.stringify(cryp.hp)}</p>
<p>{JSON.stringify(cryp.stam)}</p> <p>{JSON.stringify(cryp.stam)}</p>
</article> <button
className="button is-success"
type="submit"
onClick={() => sendCombatPve()}>
Start PVE
</button>
</section>
</div> </div>
</div> </div>
); );
@ -57,4 +63,4 @@ function InvStats({ cryp }) {
// that gets put into the dom // that gets put into the dom
} }
module.exports = InvStats; module.exports = CrypPanel;

View File

@ -10,7 +10,7 @@ const addState = connect(
} }
return { account: state.account, submitLogin }; return { account: state.account, submitLogin };
}, }
); );
module.exports = addState(Login); module.exports = addState(Login);

View File

@ -51,4 +51,4 @@ const Main = () => (
preact.render(<Main />, document.body); preact.render(<Main />, document.body);
// fizzyText('cryps.gg'); fizzyText('cryps.gg');

View File

@ -23,11 +23,9 @@ function createSocket(store) {
// https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html // https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html
let account = null; let account = null;
function send(msg) { // -------------
msg.token = account && account.token; // Incoming
ws.send(cbor.encode(msg)); // -------------
}
function accountLogin(res) { function accountLogin(res) {
const [struct, login] = res; const [struct, login] = res;
@ -43,14 +41,37 @@ function createSocket(store) {
return store.dispatch(actions.setCryp(cryp)); return store.dispatch(actions.setCryp(cryp));
} }
function combatPve(response) {
const [structName, battle] = response;
console.log('got a new battle', battle);
}
// -------------
// Outgoing
// -------------
function send(msg) {
msg.token = account && account.token;
ws.send(cbor.encode(msg));
}
function sendAccountLogin(name, password) { function sendAccountLogin(name, password) {
send({ method: 'account_login', params: { name, password } }); send({ method: 'account_login', params: { name, password } });
} }
function sendCombatPve(id) {
send({ method: 'combat_pve', params: { id } });
}
// -------------
// Handling
// -------------
// when the server sends a reply it will have one of these message types // when the server sends a reply it will have one of these message types
// this object wraps the reply types to a function // this object wraps the reply types to a function
const handlers = { const handlers = {
cryp_spawn: crypSpawn, cryp_spawn: crypSpawn,
combat_pve: combatPve,
account_login: accountLogin, account_login: accountLogin,
account_create: accountLogin, account_create: accountLogin,
}; };
@ -66,6 +87,7 @@ function createSocket(store) {
// check for error and split into response type and data // check for error and split into response type and data
if (res.err) return errorToast(res.err); if (res.err) return errorToast(res.err);
const { method, params } = res; const { method, params } = res;
if (!handlers[method]) return errorToast(`${method} handler missing`);
return handlers[method](params); return handlers[method](params);
} }
@ -90,6 +112,7 @@ function createSocket(store) {
return { return {
sendAccountLogin, sendAccountLogin,
sendCombatPve,
}; };
} }

View File

@ -32,4 +32,7 @@ physical, magic, pure dmg?
items give skills items give skills
gem td style attr combinations gem td style attr combinations
stoney + spikey = jagged stoney + spikey = jagged
slimey
ghostly

View File

@ -1,5 +1,6 @@
use ws::{Sender};
use rand::prelude::*; use rand::prelude::*;
use serde_cbor::{from_slice}; use serde_cbor::{from_slice, to_vec};
// Db Commons // Db Commons
use failure::Error; use failure::Error;
@ -78,7 +79,12 @@ pub fn keep_levelling(mut c: Cryp) -> Cryp {
fn generate_mob(plr: &Cryp) -> Cryp { fn generate_mob(plr: &Cryp) -> Cryp {
let mut rng = thread_rng(); let mut rng = thread_rng();
let mob_lvl: u8 = rng.gen_range(1, plr.lvl);
// rng panics on min == max
let mob_lvl: u8 = match plr.lvl {
1 => 1,
_ => rng.gen_range(1, plr.lvl)
};
return Cryp::new() return Cryp::new()
.named(&"bamboo basher".to_string()) .named(&"bamboo basher".to_string())
@ -87,15 +93,18 @@ fn generate_mob(plr: &Cryp) -> Cryp {
} }
pub fn pve(params: CombatPveParams, db: Db, account: Account) -> Result<Battle, Error> { pub fn pve<F>(params: CombatPveParams, db: Db, account: Account, send: F) -> Result<Battle, Error>
where F: Fn(&Battle) -> Result<(), Error>
{
let query = " let query = "
SELECT * SELECT *
FROM cryps FROM cryps
WHERE id = $1; WHERE id = $1
AND account = $2;
"; ";
let result = db let result = db
.query(query, &[&params.id])?; .query(query, &[&params.id, &account.id])?;
let returned = match result.iter().next() { let returned = match result.iter().next() {
Some(row) => row, Some(row) => row,
@ -107,7 +116,20 @@ pub fn pve(params: CombatPveParams, db: Db, account: Account) -> Result<Battle,
let 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);
return Ok(Battle::new(&plr, &mob)); let mut battle = Battle::new(&plr, &mob);
loop {
battle.next();
match send(&battle) {
Err(e) => break Err(err_msg("could not reply")),
_ => (),
};
if battle.finished() {
break Ok(battle)
}
}
} }

View File

@ -32,7 +32,7 @@ impl Handler for Server {
fn on_message(&mut self, msg: Message) -> Result<()> { fn on_message(&mut self, msg: Message) -> Result<()> {
let db = self.db.get().expect("unable to get db connection"); let db = self.db.get().expect("unable to get db connection");
match self.rpc.receive(msg, db) { match self.rpc.receive(msg, db, &self.out) {
Ok(reply) => { Ok(reply) => {
let response = to_vec(&reply) let response = to_vec(&reply)
.expect("failed to serialize response"); .expect("failed to serialize response");

View File

@ -1,5 +1,5 @@
use ws::{Message}; use ws::{Message, Sender};
use serde_cbor::{from_slice}; use serde_cbor::{from_slice, to_vec};
use uuid::Uuid; use uuid::Uuid;
use failure::Error; use failure::Error;
use failure::err_msg; use failure::err_msg;
@ -10,10 +10,35 @@ use battle::{Battle};
use combat::{pve}; use combat::{pve};
use account::{Account, create, login, from_token}; use account::{Account, create, login, from_token};
// struct Replier<T> where T: Fn(RpcResponse) {
// send: T,
// msg: RpcResponse,
// }
// impl<T> Replier<T> where T: Fn(RpcResponse) {
// fn new(send: T) -> Replier<T> {
// Replier {
// send,
// msg: None,
// }
// }
// fn msg(&mut self, arg: u32) -> u32 {
// match self.msg {
// Some(v) => v,
// None => {
// let v = (self.calculation)(arg);
// self.msg = Some(v);
// v
// },
// }
// }
// }
pub struct Rpc; pub struct Rpc;
impl Rpc { impl Rpc {
pub fn receive(&self, msg: Message, db: Db) -> Result<RpcResponse, Error> { pub fn receive(&self, msg: Message, db: Db, out: &Sender) -> Result<RpcResponse, Error> {
// consume the ws data into bytes // consume the ws data into bytes
let data = msg.into_data(); let data = msg.into_data();
@ -46,12 +71,24 @@ impl Rpc {
} }
}, },
"combat_pve" => { "combat_pve" => {
let send = |b: &Battle| -> Result<(), Error> {
let reply = RpcResponse {
method: "combat_pve".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) { match from_slice::<CombatPveMsg>(&data) {
Ok(v) => { Ok(v) => {
match account { match account {
Some(u) => Ok(RpcResponse { Some(u) => Ok(RpcResponse {
method: v.method, method: v.method,
params: RpcResult::Pve(pve(v.params, db, u)?) params: RpcResult::Pve(pve(v.params, db, u, send)?)
}), }),
None => Err(err_msg("auth required")), None => Err(err_msg("auth required")),
} }