item list

This commit is contained in:
ntr 2018-10-14 23:10:39 +11:00
parent f5cd913adf
commit b83ab923c4
10 changed files with 346 additions and 90 deletions

View File

@ -59,6 +59,7 @@ function createSocket(store) {
store.dispatch(actions.setAccount(login));
// send({ method: 'cryp_spawn', params: { name: 'muji' } });
send({ method: 'account_cryps', params: {} });
send({ method: 'item_list', params: {}});
console.log(account);
}
@ -83,6 +84,10 @@ function createSocket(store) {
console.log('got a new battle', battle);
}
function itemList(response) {
const [structName, items] = response;
console.log('got my items', items);
}
// -------------
// Outgoing
@ -113,6 +118,7 @@ function createSocket(store) {
account_login: accountLogin,
account_create: accountLogin,
account_cryps: accountCryps,
item_list: itemList,
};
// decodes the cbor and

View File

@ -0,0 +1,14 @@
exports.up = async knex => {
return knex.schema.createTable('items', table => {
table.uuid('id').primary();
table.uuid('account').notNullable()
table.foreign('account')
.references('id')
.inTable('accounts')
.onDelete('CASCADE');
table.binary('data').notNullable();
table.index('id');
});
};
exports.down = async () => {};

View File

@ -5,10 +5,11 @@
"main": "index.js",
"scripts": {
"migrate": "knex migrate:latest",
"migrate:make": "knex migrate:make --",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"license": "UNLICENSED",
"dependencies": {
"knex": "^0.15.2",
"pg": "^7.4.3"

View File

@ -3,7 +3,6 @@
* auto login
* ws reconnect ✔️
* Levelling
* KO cooldowns
* Global rolls
* Logins ✔️
* Cryp Ownership ✔
@ -14,7 +13,11 @@
* Resolve
* Stats
* Scrabble grid
* skills
* offensive -> choose target
* defensive
* Items
* rez
* Grid reroll
* Colour scheme
* Missions

View File

@ -3,13 +3,13 @@ use bcrypt::{hash, verify};
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
use std::iter;
use serde_cbor::{from_slice, to_vec};
use serde_cbor::{from_slice};
use std::str;
use net::Db;
use rpc::{AccountCreateParams, AccountLoginParams, RpcResult};
use rpc::{AccountCreateParams, AccountLoginParams};
use item::{Item, ItemAction, item_create};
use cryp::Cryp;
@ -35,7 +35,7 @@ struct AccountEntry {
// MAYBE
// hash tokens with a secret
pub fn from_token(token: String, db: &Db) -> Result<Account, Error> {
pub fn account_from_token(token: String, db: &Db) -> Result<Account, Error> {
let query = "
SELECT id, name, token
FROM accounts
@ -59,7 +59,7 @@ pub fn from_token(token: String, db: &Db) -> Result<Account, Error> {
return Ok(entry);
}
pub fn create(params: AccountCreateParams, db: &Db) -> Result<Account, Error> {
pub fn account_create(params: AccountCreateParams, db: &Db) -> Result<Account, Error> {
let id = Uuid::new_v4();
if params.password.len() < PASSWORD_MIN_LEN {
@ -86,7 +86,7 @@ pub fn create(params: AccountCreateParams, db: &Db) -> Result<Account, Error> {
RETURNING id, name, token;
";
let tx = db.transaction()?;
let mut tx = db.transaction()?;
let result = tx
.query(query, &[&account.id, &account.name, &account.password, &account.token])?;
@ -101,12 +101,16 @@ pub fn create(params: AccountCreateParams, db: &Db) -> Result<Account, Error> {
println!("{:?}", entry);
// give them a revive
let revive = Item::new(ItemAction::Revive, &entry);
item_create(revive, &mut tx, &entry)?;
tx.commit()?;
return Ok(entry);
}
pub fn login(params: AccountLoginParams, db: &Db) -> Result<Account, Error> {
pub fn account_login(params: AccountLoginParams, db: &Db) -> Result<Account, Error> {
let query = "
SELECT id, name, token, password
FROM accounts
@ -149,7 +153,7 @@ pub fn login(params: AccountLoginParams, db: &Db) -> Result<Account, Error> {
return Ok(account);
}
pub fn fetch_cryps(db: &Db, account: &Account) -> Result<Vec<Cryp>, Error> {
pub fn account_cryps(db: &Db, account: &Account) -> Result<Vec<Cryp>, Error> {
let query = "
SELECT data
FROM cryps

View File

@ -1,5 +1,3 @@
use std::{thread, time};
use rand::prelude::*;
use serde_cbor::{from_slice};
@ -11,15 +9,15 @@ use net::Db;
use account::Account;
use rpc::{CombatPveParams};
use cryp::{Cryp, write_cryp};
use cryp::{Cryp, cryp_write};
use battle::Battle;
use skill::Skill;
struct Encounter {
mob: Cryp,
success: bool,
player: Cryp,
}
// struct Encounter {
// mob: Cryp,
// success: bool,
// player: Cryp,
// }
pub fn battle_resolve(a: &Cryp, b: &Cryp) -> Battle {
@ -32,51 +30,51 @@ pub fn battle_resolve(a: &Cryp, b: &Cryp) -> Battle {
}
}
fn pve_completion(plr: Cryp) -> Encounter {
let mut rng = thread_rng();
let mob_lvl: u8 = rng.gen_range(1, plr.lvl);
// fn pve_completion(plr: Cryp) -> Encounter {
// let mut rng = thread_rng();
// let mob_lvl: u8 = rng.gen_range(1, plr.lvl);
let mob = Cryp::new()
.named(&"bamboo basher".to_string())
.level(mob_lvl)
.create();
// let mob = Cryp::new()
// .named(&"bamboo basher".to_string())
// .level(mob_lvl)
// .create();
let outcome = battle_resolve(&plr, &mob);
// let outcome = battle_resolve(&plr, &mob);
let success = match outcome.winner() {
Some(c) => c.id == plr.id,
None => false,
};
// let success = match outcome.winner() {
// Some(c) => c.id == plr.id,
// None => false,
// };
return Encounter {
mob: mob,
success,
player: plr,
};
}
// return Encounter {
// mob: mob,
// success,
// player: plr,
// };
// }
pub fn keep_levelling(mut c: Cryp) -> Cryp {
loop {
let enc = pve_completion(c);
c = enc.player;
// pub fn keep_levelling(mut c: Cryp) -> Cryp {
// loop {
// let enc = pve_completion(c);
// c = enc.player;
if !enc.success {
println!("{:?} has been KO'd", c.name);
break c;
}
// if !enc.success {
// println!("{:?} has been KO'd", c.name);
// break c;
// }
println!("{:?} rekt {:?}", c.name, enc.mob.name);
c = c.add_xp();
println!("{:?} now has {:?} xp and is lvl {:?}", c.name, c.xp, c.lvl);
// println!("{:?} rekt {:?}", c.name, enc.mob.name);
// c = c.add_xp();
// println!("{:?} now has {:?} xp and is lvl {:?}", c.name, c.xp, c.lvl);
// LEVEL CAP
if c.lvl == 12 {
break c;
}
// // LEVEL CAP
// if c.lvl == 12 {
// break c;
// }
continue;
}
}
// continue;
// }
// }
fn generate_mob(plr: &Cryp) -> Cryp {
let mut rng = thread_rng();
@ -102,7 +100,9 @@ pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle
AND account = $2;
";
let result = db
let mut tx = db.transaction()?;
let result = tx
.query(query, &[&params.id, &account.id])?;
let returned = match result.iter().next() {
@ -112,7 +112,7 @@ pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle
// tells from_slice to cast into a cryp
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)?;
// TEMP
if plr.hp.value == 0 {
@ -138,7 +138,9 @@ pub fn pve(params: CombatPveParams, db: &Db, account: &Account) -> Result<Battle
post_battle_plr = post_battle_plr.add_xp();
}
write_cryp(post_battle_plr, db, account)?;
cryp_write(post_battle_plr, &mut tx)?;
tx.commit()?;
break Ok(battle)
}
@ -173,16 +175,16 @@ pub fn test_battle() {
mod tests {
use combat::*;
#[test]
fn pve_completion_test() {
let player = Cryp::new()
.named(&"ca phe sua da".to_string())
.level(2)
.create();
// #[test]
// fn pve_completion_test() {
// let player = Cryp::new()
// .named(&"ca phe sua da".to_string())
// .level(2)
// .create();
keep_levelling(player);
return;
}
// keep_levelling(player);
// return;
// }
// #[test]
// fn pve_test() {

View File

@ -1,8 +1,9 @@
use uuid::Uuid;
use rand::prelude::*;
use serde_cbor::*;
use serde_cbor::{from_slice, to_vec};
use postgres::transaction::Transaction;
use failure::Error;
use failure::err_msg;
@ -195,7 +196,25 @@ impl Cryp {
}
pub fn spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result<Cryp, Error> {
pub fn cryp_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result<Cryp, Error> {
let query = "
SELECT data
FROM cryps
WHERE id = $1
AND account = $2;
";
let result = tx
.query(query, &[&id, &account_id])?;
let result = result.iter().next().ok_or(err_msg("cryp not found"))?;
let cryp_bytes: Vec<u8> = result.get(0);
let cryp = from_slice::<Cryp>(&cryp_bytes)?;
return Ok(cryp);
}
pub fn cryp_spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result<Cryp, Error> {
let cryp = Cryp::new()
.named(&params.name)
.level(1)
@ -215,7 +234,7 @@ pub fn spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result<Cryp
let result = tx
.query(query, &[&cryp.id, &account.id, &cryp_bytes])?;
let _returned = result.iter().next().expect("no row returned");
let _returned = result.iter().next().ok_or(err_msg("no row returned"))?;
println!("{:?} spawned cryp {:}", account.id, cryp.id);
@ -224,27 +243,22 @@ pub fn spawn(params: CrypSpawnParams, db: &Db, account: &Account) -> Result<Cryp
return Ok(cryp);
}
pub fn write_cryp(cryp: Cryp, db: &Db, account: &Account) -> Result<Cryp, Error> {
pub fn cryp_write(cryp: Cryp, tx: &mut Transaction) -> Result<Cryp, Error> {
let cryp_bytes = to_vec(&cryp)?;
let query = "
UPDATE cryps
SET data = $1
WHERE id = $2
AND account = $3
RETURNING id, account, data;
";
let tx = db.transaction()?;
let result = tx
.query(query, &[&cryp_bytes, &cryp.id, &account.id])?;
.query(query, &[&cryp_bytes, &cryp.id])?;
let _returned = result.iter().next().expect("no row returned");
println!("{:?} wrote cryp {:}", account.id, cryp.id);
tx.commit()?;
println!("{:?} wrote cryp", cryp.id);
return Ok(cryp);
}

161
server/src/item.rs Normal file
View File

@ -0,0 +1,161 @@
use account::Account;
use uuid::Uuid;
use serde_cbor::{from_slice, to_vec};
use net::Db;
use postgres::transaction::Transaction;
use rpc::{ItemUseParams};
use cryp::{cryp_get, cryp_write};
use failure::Error;
use failure::err_msg;
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum ItemAction {
Revive,
}
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub struct Item {
// mods: Vec<Mod>,
id: Uuid,
account: Uuid,
action: ItemAction,
}
impl Item {
pub fn new(action: ItemAction, account: &Account) -> Item {
let id = Uuid::new_v4();
return Item {
id,
account: account.id,
action,
};
}
fn apply(&mut self, tx: &mut Transaction, target: Uuid) -> Result<(), Error> {
match self.action {
ItemAction::Revive => revive(self, tx, target),
_ => panic!("missing item action"),
}
}
}
fn revive(item: &mut Item, tx: &mut Transaction, target: Uuid) -> Result<(), Error> {
let mut cryp = cryp_get(tx, target, item.account)?;
cryp.rez();
cryp_write(cryp, tx)?;
return Ok(());
}
pub fn item_create(item: Item, tx: &mut Transaction, account: &Account) -> Result<Item, Error> {
let item_bytes = to_vec(&item)?;
let query = "
INSERT INTO items (id, account, data)
VALUES ($1, $2, $3)
RETURNING id, account, data;
";
let result = tx
.query(query, &[&item.id, &account.id, &item_bytes])?;
let _returned = result.iter().next().expect("no row returned");
println!("{:?} wrote item {:}", account.id, item.id);
return Ok(item);
}
pub fn item_use(params: ItemUseParams, db: &Db, account: &Account) -> Result<(), Error> {
let query = "
SELECT data
FOR UPDATE
FROM items
WHERE id = $1
AND account = $2;
";
let mut tx = db.transaction()?;
let result = tx
.query(query, &[&params.item, &account.id])?;
let returned = result.iter().next().expect("no row returned");
let item_bytes: Vec<u8> = returned.get(0);
let mut item = from_slice::<Item>(&item_bytes)?;
item.apply(&mut tx, params.target)?;
tx.commit()?;
return Ok(());
}
pub fn items_list(db: &Db, account: &Account) -> Result<Vec<Item>, Error> {
let query = "
SELECT data
FROM items
WHERE account = $1;
";
let result = db
.query(query, &[&account.id])?;
let items: Result<Vec<Item>, _> = result.iter().map(|row| {
let item_bytes: Vec<u8> = row.get(0);
from_slice::<Item>(&item_bytes)
}).collect();
// catch any errors
if items.is_err() {
return Err(err_msg("could not deserialize an item"));
}
// now unwrap is safe
return Ok(items.unwrap());
}
// # max damage potion
// name
// "MapMonstersCurseEffectOnSelfFinal3": {
// "adds_tags": [],
// "domain": "area",
// "generation_type": "prefix",
// "generation_weights": [],
// "grants_buff": {},
// "grants_effect": {},
// "group": "MapHexproof",
// "is_essence_only": false,
// "name": "Hexwarded",
// "required_level": 1,
// "spawn_weights": [
// {
// "tag": "top_tier_map",
// "weight": 0
// },
// {
// "tag": "default",
// "weight": 0
// }
// ],
// "stats": [
// {
// "id": "map_item_drop_quantity_+%",
// "max": 15,
// "min": 15
// },
// {
// "id": "map_item_drop_rarity_+%",
// "max": 8,
// "min": 8
// },
// {
// "id": "map_monsters_curse_effect_on_self_+%_final",
// "max": -60,
// "min": -60
// }
// ]
// },

View File

@ -25,6 +25,7 @@ mod combat;
mod skill;
mod rpc;
mod account;
mod item;
use dotenv::dotenv;
use net::{start};

View File

@ -9,10 +9,11 @@ use failure::Error;
use failure::err_msg;
use net::Db;
use cryp::{Cryp, spawn};
use cryp::{Cryp, cryp_spawn};
use battle::{Battle};
use combat::{pve};
use account::{Account, create, login, from_token, fetch_cryps};
use account::{Account, account_create, account_login, account_from_token, account_cryps};
use item::{Item, items_list, item_use};
pub struct Rpc;
@ -26,7 +27,7 @@ impl Rpc {
Ok(v) => {
let account: Option<Account> = match v.token {
Some(t) => Some(from_token(t, &db)?),
Some(t) => Some(account_from_token(t, &db)?),
None => None,
};
@ -40,6 +41,8 @@ impl Rpc {
"account_create" => Rpc::account_create(data, db),
"account_login" => Rpc::account_login(data, db),
"account_cryps" => Rpc::account_cryps(db, account),
"item_list" => Rpc::item_list(db, account),
"item_use" => Rpc::item_use(data, db, account),
_ => Err(err_msg("unknown method")),
}
@ -57,8 +60,8 @@ impl Rpc {
}
fn combat_pve(data: Vec<u8>, db: &Db, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let u = match account {
Some(u) => u,
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
@ -66,12 +69,12 @@ impl Rpc {
let battle_response = RpcResponse {
method: "battle_state".to_string(),
params: RpcResult::Pve(pve(msg.params, db, &u)?)
params: RpcResult::Pve(pve(msg.params, db, &a)?)
};
Rpc::send_msg(client, RpcResponse {
method: "account_cryps".to_string(),
params: RpcResult::CrypList(fetch_cryps(db, &u)?)
params: RpcResult::CrypList(account_cryps(db, &a)?)
})?;
return Ok(battle_response);
@ -81,9 +84,9 @@ impl Rpc {
match from_slice::<CrypSpawnMsg>(&data) {
Ok(v) => {
match account {
Some(u) => Ok(RpcResponse {
Some(a) => Ok(RpcResponse {
method: v.method,
params: RpcResult::SpawnCryp(spawn(v.params, db, &u)?)
params: RpcResult::SpawnCryp(cryp_spawn(v.params, db, &a)?)
}),
None => Err(err_msg("auth required")),
}
@ -96,7 +99,7 @@ impl Rpc {
match from_slice::<AccountCreateMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(create(v.params, db)?)
params: RpcResult::Account(account_create(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
@ -106,7 +109,7 @@ impl Rpc {
match from_slice::<AccountLoginMsg>(&data) {
Ok(v) => Ok(RpcResponse {
method: v.method,
params: RpcResult::Account(login(v.params, db)?)
params: RpcResult::Account(account_login(v.params, db)?)
}),
Err(_e) => Err(err_msg("invalid params")),
}
@ -114,13 +117,40 @@ impl Rpc {
fn account_cryps(db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> {
match account {
Some(u) => Ok(RpcResponse {
Some(a) => Ok(RpcResponse {
method: "account_cryps".to_string(),
params: RpcResult::CrypList(fetch_cryps(db, &u)?)
params: RpcResult::CrypList(account_cryps(db, &a)?)
}),
None => Err(err_msg("auth required")),
}
}
fn item_list(db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> {
match account {
Some(a) => Ok(RpcResponse {
method: "item_list".to_string(),
params: RpcResult::ItemList(items_list(db, &a)?)
}),
None => Err(err_msg("auth required")),
}
}
fn item_use(data: Vec<u8>, db: &Db, account: Option<Account>) -> Result<RpcResponse, Error> {
match from_slice::<ItemUseMsg>(&data) {
Ok(v) => {
match account {
Some(a) => Ok(RpcResponse {
method: v.method,
params: RpcResult::ItemUse(item_use(v.params, db, &a)?)
}),
None => Err(err_msg("auth required")),
}
}
Err(_e) => Err(err_msg("invalid params")),
}
}
}
#[derive(Debug,Clone,Serialize,Deserialize)]
@ -135,6 +165,8 @@ pub enum RpcResult {
Account(Account),
CrypList(Vec<Cryp>),
Pve(Battle),
ItemList(Vec<Item>),
ItemUse(()),
}
#[derive(Debug,Clone,Serialize,Deserialize)]
@ -195,6 +227,24 @@ struct AccountCrypsMsg {
params: (),
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct ItemListMsg {
method: String,
params: (),
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct ItemUseMsg {
method: String,
params: ItemUseParams,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct ItemUseParams {
pub item: Uuid,
pub target: Uuid,
}
// #[cfg(test)]
// mod tests {
// use super::*;