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 InvStats = require('./invstats');
const CrypPanel = require('./cryp.panel');
// Add the incident from state as a property
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');
function InvStats({ cryp }) {
function CrypPanel({ cryp, sendCombatPve }) {
if (!cryp) return <div>not ready</div>;
return (
<div className="tile is-ancestor has-text-centered has-background-grey is-dark is-10">
<div className="tile is-6">
<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>
</article>
<article className="tile is-child notification is-success">
</section>
<section className="tile is-child notification is-success">
<p>Body Armor</p>
</article>
<article className="tile is-child notification is-success">
</section>
<section className="tile is-child notification is-success">
<p>Gloves</p>
</article>
<article className="tile is-child notification is-success">
</section>
<section className="tile is-child notification is-success">
<p>Boots</p>
</article>
</section>
</div>
<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">
<svg width="160" height="160" data-jdenticon-value={cryp.name} />
</figure>
<p className="title">{cryp.name}</p>
<p className="subtitle">The big boy</p>
</article>
</section>
</div>
<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>
</article>
<article className="tile is-child notification is-dark">
</section>
<section className="tile is-child notification is-dark">
<p>Jewellery</p>
</article>
<article className="tile is-child notification is-dark">
</section>
<section className="tile is-child notification is-dark">
<p>Artifact</p>
</article>
</section>
</div>
</div>
<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>{JSON.stringify(cryp.def)}</p>
<p>{JSON.stringify(cryp.dmg)}</p>
<p>{JSON.stringify(cryp.hp)}</p>
<p>{JSON.stringify(cryp.stam)}</p>
</article>
<button
className="button is-success"
type="submit"
onClick={() => sendCombatPve()}>
Start PVE
</button>
</section>
</div>
</div>
);
@ -57,4 +63,4 @@ function InvStats({ cryp }) {
// 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 };
},
}
);
module.exports = addState(Login);

View File

@ -51,4 +51,4 @@ const Main = () => (
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
let account = null;
function send(msg) {
msg.token = account && account.token;
ws.send(cbor.encode(msg));
}
// -------------
// Incoming
// -------------
function accountLogin(res) {
const [struct, login] = res;
@ -43,14 +41,37 @@ function createSocket(store) {
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) {
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
// this object wraps the reply types to a function
const handlers = {
cryp_spawn: crypSpawn,
combat_pve: combatPve,
account_login: accountLogin,
account_create: accountLogin,
};
@ -66,6 +87,7 @@ function createSocket(store) {
// check for error and split into response type and data
if (res.err) return errorToast(res.err);
const { method, params } = res;
if (!handlers[method]) return errorToast(`${method} handler missing`);
return handlers[method](params);
}
@ -90,6 +112,7 @@ function createSocket(store) {
return {
sendAccountLogin,
sendCombatPve,
};
}

View File

@ -32,4 +32,7 @@ physical, magic, pure dmg?
items give skills
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 serde_cbor::{from_slice};
use serde_cbor::{from_slice, to_vec};
// Db Commons
use failure::Error;
@ -78,7 +79,12 @@ pub fn keep_levelling(mut c: Cryp) -> Cryp {
fn generate_mob(plr: &Cryp) -> Cryp {
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()
.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 = "
SELECT *
FROM cryps
WHERE id = $1;
WHERE id = $1
AND account = $2;
";
let result = db
.query(query, &[&params.id])?;
.query(query, &[&params.id, &account.id])?;
let returned = match result.iter().next() {
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 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<()> {
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) => {
let response = to_vec(&reply)
.expect("failed to serialize response");

View File

@ -1,5 +1,5 @@
use ws::{Message};
use serde_cbor::{from_slice};
use ws::{Message, Sender};
use serde_cbor::{from_slice, to_vec};
use uuid::Uuid;
use failure::Error;
use failure::err_msg;
@ -10,10 +10,35 @@ use battle::{Battle};
use combat::{pve};
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;
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
let data = msg.into_data();
@ -46,12 +71,24 @@ impl Rpc {
}
},
"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) {
Ok(v) => {
match account {
Some(u) => Ok(RpcResponse {
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")),
}