diff --git a/client/src/scenes/cryps.js b/client/src/scenes/cryps.js index 35596c5e..b95f6bbb 100644 --- a/client/src/scenes/cryps.js +++ b/client/src/scenes/cryps.js @@ -29,7 +29,7 @@ function renderCryps() { }, }, scene: [ - Background, + // Background, Header, ], }; diff --git a/client/src/scenes/menu.js b/client/src/scenes/menu.js index 03bce852..77a1c53b 100644 --- a/client/src/scenes/menu.js +++ b/client/src/scenes/menu.js @@ -25,6 +25,7 @@ const MAIN_MENU_SCENES = [ 'ItemInfo', ]; +const NULL_UUID = '00000000-0000-0000-0000-000000000000'; class Menu extends Phaser.Scene { constructor() { @@ -37,7 +38,7 @@ class Menu extends Phaser.Scene { // When we load the menu request the latest items // Item list will restart when the data comes in - this.registry.get('ws').sendAccountItems(); + this.registry.get('ws').sendVboxState(NULL_UUID); this.scene.manager.add('MenuCrypList', MenuCrypList, true); this.scene.manager.add('MenuNavigation', MenuNavigation, true); diff --git a/client/src/socket.js b/client/src/socket.js index e947278a..3ff77ca6 100644 --- a/client/src/socket.js +++ b/client/src/socket.js @@ -1,6 +1,7 @@ const toast = require('izitoast'); const cbor = require('borc'); + const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://cryps.gg/ws' : 'ws://localhost:40000'; function errorToast(err) { @@ -44,10 +45,6 @@ function createSocket(events) { send({ method: 'account_cryps', params: {} }); } - function sendAccountItems() { - send({ method: 'account_items', params: {} }); - } - function sendAccountZone() { send({ method: 'account_zone', params: {} }); } @@ -88,6 +85,10 @@ function createSocket(events) { send({ method: 'cryp_unspec', params: { id, spec } }); } + function sendVboxState(gameId) { + send({ method: 'vbox_state', params: { game_id: gameId } }); + } + function sendPressR() { send({ method: 'press_r', params: { } }); @@ -162,11 +163,6 @@ function createSocket(events) { const [structName, game] = response; } - function accountItems(response) { - const [structName, items] = response; - events.setItems(items); - } - function zoneState(response) { const [structName, zone] = response; events.setZone(zone); @@ -188,7 +184,6 @@ function createSocket(events) { account_login: accountLogin, account_create: accountLogin, account_cryps: accountCryps, - account_items: accountItems, zone_create: res => console.log(res), zone_state: zoneState, zone_close: res => console.log(res), @@ -268,7 +263,6 @@ function createSocket(events) { sendAccountCreate, sendAccountDemo, sendAccountCryps, - sendAccountItems, sendAccountZone, sendGameState, sendGamePve, @@ -285,6 +279,7 @@ function createSocket(events) { sendZoneCreate, sendZoneJoin, sendZoneClose, + sendVboxState, connect, }; } diff --git a/ops/migrations/20181014141623_items.js b/ops/migrations/20181014141623_items.js deleted file mode 100644 index 97c7c8c9..00000000 --- a/ops/migrations/20181014141623_items.js +++ /dev/null @@ -1,15 +0,0 @@ -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'); - table.index('account'); - }); -}; - -exports.down = async () => {}; \ No newline at end of file diff --git a/ops/migrations/20190216123550_vbox.js b/ops/migrations/20190216123550_vbox.js new file mode 100644 index 00000000..4ed2fcae --- /dev/null +++ b/ops/migrations/20190216123550_vbox.js @@ -0,0 +1,36 @@ +const NULL_UUID = '00000000-0000-0000-0000-000000000000'; + +exports.up = async knex => { + await knex.schema.createTable('vbox', table => { + table.timestamps(); + table.uuid('id').primary(); + table.uuid('account').notNullable() + table.uuid('game').notNullable() + table.binary('data').notNullable(); + + table.foreign('game') + .references('id') + .inTable('games') + .onDelete('CASCADE'); + + table.foreign('account') + .references('id') + .inTable('accounts') + .onDelete('CASCADE'); + + table.index('id'); + table.index('account'); + table.unique(['account', 'game']); + }); + + // not really sure if this is a good idea + await knex('games').insert({ + id: NULL_UUID, + data: 'INVALID', + joinable: false, + }); + + return true; +}; + +exports.down = async () => {}; \ No newline at end of file diff --git a/ops/package.json b/ops/package.json index 6ac74db4..3ee5cdf7 100755 --- a/ops/package.json +++ b/ops/package.json @@ -11,9 +11,6 @@ "author": "", "license": "UNLICENSED", "dependencies": { - "ascii-tree": "^0.3.0", - "cli-ascii-tree": "0.0.4", - "inquirer": "^6.2.0", "knex": "^0.15.2", "pg": "^7.4.3" } diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 05578200..8eb9771a 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -56,10 +56,6 @@ taunt ## NOW -rename physical and spell - - - inventory + drops table id account diff --git a/server/src/item.rs b/server/src/item.rs index e2163d2c..4f499842 100644 --- a/server/src/item.rs +++ b/server/src/item.rs @@ -44,9 +44,9 @@ impl Item { pub fn new(action: ItemAction, account_id: Uuid) -> Item { let id = Uuid::new_v4(); return Item { - id, - account: account_id, - action, + id, + account: account_id, + action, }; } diff --git a/server/src/main.rs b/server/src/main.rs index 5c859276..31cef43c 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -30,6 +30,8 @@ mod item; mod zone; mod mob; +mod vbox; + use dotenv::dotenv; use net::{start}; diff --git a/server/src/rpc.rs b/server/src/rpc.rs index ea9bc122..0b6a5774 100644 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -22,6 +22,7 @@ use item::{Item, ItemAction, items_list, item_use, item_create}; use skill::{Skill}; use zone::{Zone, zone_create, zone_join, zone_close}; use spec::{Spec}; +use vbox::{Vbox, vbox_state, vbox_accept, vbox_combine}; pub struct Rpc; @@ -80,6 +81,10 @@ impl Rpc { "account_zone" => Rpc::account_zone(data, &mut tx, account.unwrap(), client), "item_use" => Rpc::item_use(data, &mut tx, account.unwrap(), client), + "vbox_state" => Rpc::vbox_state(data, &mut tx, account.unwrap(), client), + "vbox_accept" => Rpc::vbox_accept(data, &mut tx, account.unwrap(), client), + "vbox_combine" => Rpc::vbox_combine(data, &mut tx, account.unwrap(), client), + "press_r" => Rpc::press_r(data, &mut tx, account.unwrap(), client), _ => Err(format_err!("unknown method - {:?}", v.method)), @@ -251,8 +256,6 @@ impl Rpc { Ok(cryp_list) } - - fn account_create(data: Vec, tx: &mut Transaction, _client: &mut WebSocket) -> Result { match from_slice::(&data) { Ok(v) => Ok(RpcResponse { @@ -404,6 +407,39 @@ impl Rpc { return Ok(response); } + fn vbox_state(data: Vec, tx: &mut Transaction, account: Account, _client: &mut WebSocket) -> Result { + let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; + + let response = RpcResponse { + method: "vbox_state".to_string(), + params: RpcResult::VboxState(vbox_state(msg.params, tx, &account)?) + }; + + return Ok(response); + } + + fn vbox_accept(data: Vec, tx: &mut Transaction, account: Account, _client: &mut WebSocket) -> Result { + let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; + + let response = RpcResponse { + method: "vbox_state".to_string(), + params: RpcResult::VboxState(vbox_accept(msg.params, tx, &account)?) + }; + + return Ok(response); + } + + fn vbox_combine(data: Vec, tx: &mut Transaction, account: Account, _client: &mut WebSocket) -> Result { + let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; + + let response = RpcResponse { + method: "vbox_state".to_string(), + params: RpcResult::VboxState(vbox_combine(msg.params, tx, &account)?) + }; + + return Ok(response); + } + } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -426,6 +462,8 @@ pub enum RpcResult { ItemUse(()), ZoneState(Zone), ZoneClose(()), + + VboxState(Vbox), } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -637,6 +675,40 @@ pub struct ZoneCloseParams { pub zone_id: Uuid, } +#[derive(Debug,Clone,Serialize,Deserialize)] +struct VboxStateMsg { + method: String, + params: VboxStateParams, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct VboxStateParams { + pub game_id: Uuid, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +struct VboxBuyMsg { + method: String, + params: VboxBuyParams, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct VboxBuyParams { + pub game_id: Uuid, + pub index: u8, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +struct VboxCombineMsg { + method: String, + params: VboxCombineParams, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct VboxCombineParams { + pub game_id: Uuid, + pub indices: Vec, +} // #[cfg(test)] // mod tests { diff --git a/server/src/vbox.rs b/server/src/vbox.rs new file mode 100644 index 00000000..7cb7a3ff --- /dev/null +++ b/server/src/vbox.rs @@ -0,0 +1,117 @@ +use uuid::Uuid; +use rand::prelude::*; +use serde_cbor::{from_slice, to_vec}; + +use postgres::transaction::Transaction; + +use failure::Error; +use failure::err_msg; + +use account::Account; +use rpc::{VboxStateParams, VboxBuyParams, VboxCombineParams}; +use item::{Item}; + +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct Vbox { + pub id: Uuid, + pub balance: u16, + pub free: Vec, + pub bound: Vec, + pub game: Uuid, + pub account: Uuid, +} + +impl Vbox { + pub fn new(account_id: Uuid, game_id: Uuid) -> Vbox { + Vbox { + id: Uuid::new_v4(), + account: account_id, + game: game_id, + free: vec![], + bound: vec![], + balance: 0, + } + } +} + +pub fn vbox_write(vbox: Vbox, tx: &mut Transaction, account: &Account) -> Result { + let vbox_bytes = to_vec(&vbox)?; + + let query = " + INSERT INTO vbox (id, account, game, data) + VALUES ($1, $2, $3, $4) + RETURNING id; + "; + + let result = tx + .query(query, &[&vbox.id, &account.id, &vbox.game, &vbox_bytes])?; + + result.iter().next().ok_or(format_err!("no vbox written"))?; + + // println!("{:} wrote vbox", vbox.id); + + return Ok(vbox); +} + +pub fn vbox_get(tx: &mut Transaction, game_id: Uuid, account: &Account) -> Result { + let query = " + SELECT * + FROM vbox + WHERE account = $1 + AND game = $2; + "; + + let result = tx + .query(query, &[&account.id, &game_id])?; + + let returned = match result.iter().next() { + Some(row) => row, + None => return Err(err_msg("vbox not found")), + }; + + // tells from_slice to cast into a cryp + let vbox_bytes: Vec = returned.get("data"); + let vbox = from_slice::(&vbox_bytes)?; + + return Ok(vbox); +} + +pub fn vbox_state(params: VboxStateParams, tx: &mut Transaction, account: &Account) -> Result { + match vbox_get(tx, params.game_id, account) { + Ok(v) => Ok(v), + Err(e) => { + println!("{:?}", e); + vbox_write(Vbox::new(account.id, params.game_id), tx, account) + } + } +} + +pub fn vbox_accept(params: VboxBuyParams, tx: &mut Transaction, account: &Account) -> Result { + return vbox_get(tx, params.game_id, account) +} + +pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &Account) -> Result { + return vbox_get(tx, params.game_id, account) +} + + +// pub fn item_drop(tx: &mut Transaction, account_id: Uuid, mode: GameMode) -> Result<(), Error> { +// let mut rng = thread_rng(); + +// let log_normal = LogNormal::new(1.0, 1.0); +// let num_drops = log_normal.sample(&mut rng).floor() as u16; + +// let actions = mode_drops(mode); +// println!("{:?} drops", num_drops); + +// for _i in 0..num_drops { +// let dist = WeightedIndex::new(actions.iter().map(|item| item.1)).unwrap(); +// let kind = actions[dist.sample(&mut rng)].0; +// let item = Item::new(kind, account_id); + +// println!("{:?} dropped {:?}", account_id, item); +// item_create(item, tx, account_id)?; +// } + +// Ok(()) +// }