- {abandonBtn}
- {concedeBtn}
- {drawBtn}
+ {authBtn(abandonBtn)}
+ {authBtn(concedeBtn)}
+ {authBtn(drawBtn)}
);
}
diff --git a/client/src/components/instance.ctrl.top.btns.jsx b/client/src/components/instance.ctrl.top.btns.jsx
index 7fc4f018..319298d7 100644
--- a/client/src/components/instance.ctrl.top.btns.jsx
+++ b/client/src/components/instance.ctrl.top.btns.jsx
@@ -7,6 +7,7 @@ const addState = connect(
function receiveState(state) {
const {
ws,
+ authenticated,
instance,
tutorial,
} = state;
@@ -17,6 +18,7 @@ const addState = connect(
return {
instance,
+ authenticated,
tutorial,
sendAbandon,
};
@@ -39,6 +41,7 @@ const addState = connect(
function InstanceTopBtns(args) {
const {
instance,
+ authenticated,
leave,
sendAbandon,
@@ -61,9 +64,16 @@ function InstanceTopBtns(args) {
const abandonBtn =
- {finished ? leaveBtn : abandonBtn}
+ {finalBtn()}
);
}
diff --git a/client/src/components/play.jsx b/client/src/components/play.jsx
index 2c97b77f..e731ad5c 100644
--- a/client/src/components/play.jsx
+++ b/client/src/components/play.jsx
@@ -232,7 +232,6 @@ function Play(args) {
diff --git a/client/src/components/vbox.utils.jsx b/client/src/components/vbox.utils.jsx
index 4a4a90d1..9fcaca5c 100644
--- a/client/src/components/vbox.utils.jsx
+++ b/client/src/components/vbox.utils.jsx
@@ -96,7 +96,7 @@ function genItemInfo(item, itemInfo, player) {
itemSourceInfo = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
}
- const cooldown = isSkill && fullInfo.cooldown ?
{fullInfo.cooldown} Turn delay
: null;
+ const cooldown = isSkill && fullInfo.cooldown ?
{fullInfo.delay} turn delay, {fullInfo.cooldown} turn cooldown
: null;
const speed = isSkill
?
Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
diff --git a/client/src/components/welcome.jsx b/client/src/components/welcome.jsx
index 8270cdb2..d32c5997 100644
--- a/client/src/components/welcome.jsx
+++ b/client/src/components/welcome.jsx
@@ -1,13 +1,31 @@
// eslint-disable-next-line
const preact = require('preact');
+const { connect } = require('preact-redux');
const Login = require('./welcome.login');
const Register = require('./welcome.register');
const Help = require('./welcome.help');
// const About = require('./welcome.about');
-function Welcome() {
- const page = this.state.page || 'login';
+const addState = connect(
+ function receiveState(state) {
+ const {
+ tutorial,
+ } = state;
+
+ return {
+ promptRegister: tutorial === 99, // see events
+ };
+ },
+);
+
+function Welcome(args) {
+
+ const {
+ promptRegister,
+ } = args;
+
+ const page = this.state.page || promptRegister && 'register' || 'login';
const pageEl = () => {
if (page === 'login') return
;
@@ -45,4 +63,4 @@ function Welcome() {
);
}
-module.exports = Welcome;
+module.exports = addState(Welcome);
diff --git a/client/src/constants.jsx b/client/src/constants.jsx
index c6b6dfaf..39b38535 100644
--- a/client/src/constants.jsx
+++ b/client/src/constants.jsx
@@ -71,7 +71,7 @@ module.exports = {
},
speedStat: {
item: 'SPEED',
- description: 'Speed determines the order in which skills resolve.\nCombine SPEED specs to increase speed.',
+ description: 'Speed determines the order in which skills resolve.\nThe initial delay of skills is reduced by 1 turn for every 250 speed.\nCombine SPEED specs to increase speed.',
},
},
};
diff --git a/client/src/events.jsx b/client/src/events.jsx
index 11e791ea..a0e6a307 100644
--- a/client/src/events.jsx
+++ b/client/src/events.jsx
@@ -218,6 +218,10 @@ function registerEvents(store) {
store.dispatch(actions.setTutorial(1));
}
+ function promptRegister() {
+ store.dispatch(actions.setTutorial(99));
+ store.dispatch(actions.setInstance(null));
+ }
window.addEventListener('hashchange', urlHashChange, false);
@@ -250,6 +254,7 @@ function registerEvents(store) {
setWs,
startTutorial,
+ promptRegister,
urlHashChange,
diff --git a/client/src/socket.jsx b/client/src/socket.jsx
index 30e16b59..a7e2916c 100644
--- a/client/src/socket.jsx
+++ b/client/src/socket.jsx
@@ -301,6 +301,7 @@ function createSocket(events) {
// Joining: () => events.notify('Searching for instance...'),
StartTutorial: () => events.startTutorial(),
+ PromptRegister: () => events.promptRegister(),
Processing: () => true,
Error: errHandler,
diff --git a/core/Cargo.toml b/core/Cargo.toml
index f128fda1..4edb5c25 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mnml_core"
-version = "1.11.2"
+version = "1.12.0"
authors = ["ntr
", "mashy "]
[dependencies]
diff --git a/core/src/construct.rs b/core/src/construct.rs
index 3a11d06d..2c45b7be 100644
--- a/core/src/construct.rs
+++ b/core/src/construct.rs
@@ -52,10 +52,14 @@ impl ConstructSkill {
pub fn new(skill: Skill) -> ConstructSkill {
ConstructSkill {
skill,
- cd: skill.base_cd(),
+ cd: skill.delay(),
disabled: false,
}
}
+
+ pub fn set_cooldown(&mut self, cd: Cooldown) -> () {
+ self.cd = cd;
+ }
}
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
@@ -432,15 +436,34 @@ impl Construct {
self.skills.iter().find(|s| s.skill == skill && s.cd.is_some())
}
+ pub fn set_construct_delays(&mut self) -> () {
+ // for every multiple of speed threshold delays are reduced by 1 at start of game
+ let speed_threshold = 250;
+ let delay_reduction = self.speed.value.wrapping_div(speed_threshold);
+
+ self.skills
+ .iter_mut()
+ .for_each(|s| match s.skill.delay() {
+ Some(cd) => match cd.saturating_sub(delay_reduction) {
+ 0 => s.set_cooldown(None),
+ _ => s.set_cooldown(Some(cd.saturating_sub(delay_reduction)))
+ },
+ None => s.set_cooldown(None)
+ });
+ }
+
pub fn skill_set_cd(&mut self, skill: Skill) -> &mut Construct {
// println!("{:?} {:?} skill cooldown set", self.name, skill);
// tests force resolve some skills
// which cause the game to attempt to put them on cd
// even though the construct doesn't know the skill
- if let Some(i) = self.skills.iter().position(|s| s.skill == skill) {
- self.skills.remove(i);
- self.skills.insert(i, ConstructSkill::new(skill));
+ // if let Some(i) = self.skills.iter().position(|s| s.skill == skill) {
+ // self.skills.remove(i);
+ // self.skills.insert(i, ConstructSkill::new(skill));
+ //}
+ if let Some(sk) = self.skills.iter_mut().find(|s| s.skill == skill) {
+ sk.set_cooldown(skill.base_cd());
}
self
@@ -1218,7 +1241,7 @@ mod tests {
i += 1;
}
- assert_eq!(i, Skill::Sleep.base_cd().unwrap());
+ assert_eq!(i, Skill::Sleep.delay().unwrap());
}
}
diff --git a/core/src/game.rs b/core/src/game.rs
index fbb8f187..5364013b 100644
--- a/core/src/game.rs
+++ b/core/src/game.rs
@@ -104,7 +104,6 @@ impl Game {
// let player_description = player.constructs.iter().map(|c| c.name.clone()).collect::>().join(", ");
// self.log.push(format!("{:} has joined the game. [{:}]", player.name, player_description));
- player.constructs.sort_unstable_by_key(|c| c.id);
self.players.push(player);
Ok(self)
@@ -140,12 +139,19 @@ impl Game {
&& self.players.iter().all(|t| t.constructs.len() == self.player_constructs)
}
- pub fn start(self) -> Game {
+ pub fn start(mut self) -> Game {
// both forfeit ddue to no skills
if self.finished() {
return self.finish();
}
+ self.players
+ .iter_mut()
+ .for_each(|p| p.constructs
+ .iter_mut()
+ .for_each(|c| c.set_construct_delays())
+ );
+
self.skill_phase_start(0)
}
@@ -1163,6 +1169,44 @@ mod tests {
return;
}
+ #[test]
+ fn delay_test() {
+ let mut x = Construct::new()
+ .named(&"pronounced \"creeep\"".to_string())
+ .learn(Skill::Ruin);
+
+ let mut y = Construct::new()
+ .named(&"lemongrass tea".to_string())
+ .learn(Skill::Ruin);
+
+ // Ruin has 2 turn cd
+ // 250 speed = 1 cd delay reduction
+ x.speed.force(499);
+ y.speed.force(700);
+
+ let mut game = Game::new();
+ game.set_player_num(2).set_player_constructs(1);
+
+ let x_player_id = Uuid::new_v4();
+ x.account = x_player_id;
+ let x_player = Player::new(x_player_id, None, &"ntr".to_string(), vec![x]);
+
+ let y_player_id = Uuid::new_v4();
+ y.account = y_player_id;
+ let y_player = Player::new(y_player_id, None, &"mash".to_string(), vec![y]);
+
+ game
+ .player_add(x_player).unwrap()
+ .player_add(y_player).unwrap();
+
+ game = game.start();
+
+ assert!(game.players[0].constructs[0].skill_on_cd(Skill::Ruin).is_some());
+ assert!(game.players[1].constructs[0].skill_on_cd(Skill::Ruin).is_none());
+ }
+
+
+
#[test]
fn stun_test() {
let mut game = create_test_game();
@@ -1240,7 +1284,7 @@ mod tests {
// should auto progress back to skill phase
assert!(game.phase == Phase::Skill);
- assert!(game.player_by_id(y_player.id).unwrap().constructs[0].skill_on_cd(Skill::Stun).is_some());
+ assert!(game.player_by_id(y_player.id).unwrap().constructs[0].skill_on_cd(Skill::Stun).is_none());
assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Block).is_none());
game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Attack).unwrap();
diff --git a/core/src/item.rs b/core/src/item.rs
index 185b1832..9b13f568 100644
--- a/core/src/item.rs
+++ b/core/src/item.rs
@@ -1362,6 +1362,7 @@ pub struct ItemInfo {
pub values: Option,
pub skill: bool,
pub speed: Option,
+ pub delay: Cooldown,
pub cooldown: Cooldown,
pub description: String,
}
@@ -1406,6 +1407,10 @@ pub fn item_info() -> ItemInfoCtr {
Some(s) => s.base_cd(),
None => None
},
+ delay: match v.into_skill() {
+ Some(s) => s.delay(),
+ None => None
+ },
})
.collect::>();
diff --git a/core/src/player.rs b/core/src/player.rs
index 21556a0b..0b686a60 100644
--- a/core/src/player.rs
+++ b/core/src/player.rs
@@ -65,7 +65,9 @@ pub struct Player {
}
impl Player {
- pub fn new(account: Uuid, img: Option, name: &String, constructs: Vec) -> Player {
+ pub fn new(account: Uuid, img: Option, name: &String, mut constructs: Vec) -> Player {
+ constructs.sort_unstable_by_key(|c| c.id);
+
Player {
id: account,
img,
diff --git a/core/src/skill.rs b/core/src/skill.rs
index 653719f2..f26729a5 100644
--- a/core/src/skill.rs
+++ b/core/src/skill.rs
@@ -522,6 +522,157 @@ impl Skill {
Skill::SustainPlus |
Skill::SustainPlusPlus => Some(1),
+ Skill::Intercept => Some(2),
+ Skill::InterceptPlus => Some(2),
+ Skill::InterceptPlusPlus => Some(2),
+
+ Skill::Electrify |
+ Skill::ElectrifyPlus |
+ Skill::ElectrifyPlusPlus => None,
+
+ Skill::Absorb |
+ Skill::AbsorbPlus |
+ Skill::AbsorbPlusPlus => Some(1),
+
+ //-----------
+ // Never cast directly
+ //---------
+ // Trigger
+ Skill::HybridBlast |
+ Skill::HasteStrike |
+ Skill::CounterAttack|
+ Skill::CounterAttackPlus |
+ Skill::CounterAttackPlusPlus | // counter
+ Skill::Electrocute|
+ Skill::ElectrocutePlus |
+ Skill::ElectrocutePlusPlus |
+ Skill::Absorption|
+ Skill::AbsorptionPlus |
+ Skill::AbsorptionPlusPlus |
+ // Ticks
+ Skill::ElectrocuteTick|
+ Skill::DecayTick|
+ Skill::SiphonTick|
+ Skill::TriageTick => None,
+ }
+ }
+
+ pub fn delay(&self) -> Cooldown {
+ match self {
+ Skill::Attack => None,
+ Skill::Block => None, // reduce damage
+ Skill::Buff => None,
+ Skill::Debuff => None,
+ Skill::Stun => Some(1),
+
+ Skill::Strike=> None,
+ Skill::StrikePlus => None,
+ Skill::StrikePlusPlus => None,
+
+ Skill::Counter|
+ Skill::CounterPlus |
+ Skill::CounterPlusPlus => None,
+
+ Skill::Restrict |
+ Skill::RestrictPlus |
+ Skill::RestrictPlusPlus => Some(1),
+
+ Skill::Bash |
+ Skill::BashPlus |
+ Skill::BashPlusPlus => Some(1),
+
+ Skill::Heal=> None,
+ Skill::HealPlus => None,
+ Skill::HealPlusPlus => None,
+
+ Skill::Triage=> None, // hot
+ Skill::TriagePlus => None, // hot
+ Skill::TriagePlusPlus => None, // hot
+
+ Skill::Break | // no damage stun, adds vulnerable
+ Skill::BreakPlus |
+ Skill::BreakPlusPlus => Some(1),
+
+ Skill::Blast |
+ Skill::BlastPlus |
+ Skill::BlastPlusPlus => None,
+
+ Skill::Chaos |
+ Skill::ChaosPlus |
+ Skill::ChaosPlusPlus => None,
+
+ Skill::Amplify |
+ Skill::AmplifyPlus |
+ Skill::AmplifyPlusPlus => Some(1),
+
+ Skill::Hybrid |
+ Skill::HybridPlus |
+ Skill::HybridPlusPlus => Some(1),
+
+ Skill::Invert |
+ Skill::InvertPlus |
+ Skill::InvertPlusPlus => Some(2),
+
+ Skill::Decay => None, // dot
+ Skill::DecayPlus => None,
+ Skill::DecayPlusPlus => None,
+
+ Skill::Siphon|
+ Skill::SiphonPlus |
+ Skill::SiphonPlusPlus => None,
+
+ Skill::Curse |
+ Skill::CursePlus |
+ Skill::CursePlusPlus => Some(1),
+
+ Skill::Link |
+ Skill::LinkPlus |
+ Skill::LinkPlusPlus => Some(1),
+
+ Skill::Silence |
+ Skill::SilencePlus |
+ Skill::SilencePlusPlus => Some(1),
+
+ Skill::Purify |
+ Skill::PurifyPlus |
+ Skill::PurifyPlusPlus => None,
+
+ Skill::Purge |
+ Skill::PurgePlus |
+ Skill::PurgePlusPlus => Some(1),
+
+ Skill::Banish |
+ Skill::BanishPlus |
+ Skill::BanishPlusPlus => Some(1),
+
+ Skill::Haste |
+ Skill::HastePlus |
+ Skill::HastePlusPlus => Some(1),
+
+ Skill::Reflect |
+ Skill::ReflectPlus |
+ Skill::ReflectPlusPlus => None,
+
+ Skill::Recharge |
+ Skill::RechargePlus |
+ Skill::RechargePlusPlus => None,
+
+ Skill::Ruin |
+ Skill::RuinPlus |
+ Skill::RuinPlusPlus => Some(2),
+
+ Skill::Slay=> None,
+ Skill::SlayPlus => None,
+ Skill::SlayPlusPlus => None,
+
+ Skill::Sleep |
+ Skill::SleepPlus |
+ Skill::SleepPlusPlus => Some(1),
+
+ Skill::Sustain |
+ Skill::SustainPlus |
+ Skill::SustainPlusPlus => Some(1),
+
Skill::Intercept => Some(1),
Skill::InterceptPlus => Some(1),
Skill::InterceptPlusPlus => Some(1),
diff --git a/ops/package.json b/ops/package.json
index 9a1ed953..3b993c63 100644
--- a/ops/package.json
+++ b/ops/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-ops",
- "version": "1.11.2",
+ "version": "1.12.0",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/server/Cargo.toml b/server/Cargo.toml
index 16ced6b7..9f7e199a 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mnml"
-version = "1.11.2"
+version = "1.12.0"
authors = ["ntr "]
[dependencies]
diff --git a/server/src/account.rs b/server/src/account.rs
index 08d1ca74..f180cf70 100644
--- a/server/src/account.rs
+++ b/server/src/account.rs
@@ -213,42 +213,42 @@ pub fn new_img(tx: &mut Transaction, id: Uuid) -> Result {
Account::try_from(row)
}
-pub fn set_password(tx: &mut Transaction, id: Uuid, current: &String, password: &String) -> Result {
+pub fn set_password(tx: &mut Transaction, id: Uuid, password: &String) -> Result {
if password.len() < PASSWORD_MIN_LEN || password.len() > 100 {
return Err(MnmlHttpError::PasswordUnacceptable);
}
- let query = "
- SELECT id, password
- FROM accounts
- WHERE id = $1
- ";
+ // let query = "
+ // SELECT id, password
+ // FROM accounts
+ // WHERE id = $1
+ // ";
- let result = tx
- .query(query, &[&id])?;
+ // let result = tx
+ // .query(query, &[&id])?;
- let row = match result.iter().next() {
- Some(row) => row,
- None => {
- let mut rng = thread_rng();
- let garbage: String = iter::repeat(())
- .map(|()| rng.sample(Alphanumeric))
- .take(64)
- .collect();
+ // let row = match result.iter().next() {
+ // Some(row) => row,
+ // None => {
+ // let mut rng = thread_rng();
+ // let garbage: String = iter::repeat(())
+ // .map(|()| rng.sample(Alphanumeric))
+ // .take(64)
+ // .collect();
- // verify garbage to prevent timing attacks
- verify(garbage.clone(), &garbage).ok();
- return Err(MnmlHttpError::AccountNotFound);
- },
- };
+ // // verify garbage to prevent timing attacks
+ // verify(garbage.clone(), &garbage).ok();
+ // return Err(MnmlHttpError::AccountNotFound);
+ // },
+ // };
- let id: Uuid = row.get(0);
- let db_pw: String = row.get(1);
+ // let id: Uuid = row.get(0);
+ // let db_pw: String = row.get(1);
- // return bad request to prevent being logged out
- if !verify(current, &db_pw)? {
- return Err(MnmlHttpError::BadRequest);
- }
+ // // return bad request to prevent being logged out
+ // if !verify(current, &db_pw)? {
+ // return Err(MnmlHttpError::BadRequest);
+ // }
let password = hash(&password, PASSWORD_ROUNDS)?;
diff --git a/server/src/http.rs b/server/src/http.rs
index 88e7b51b..34b3b994 100644
--- a/server/src/http.rs
+++ b/server/src/http.rs
@@ -369,7 +369,7 @@ fn recover(req: &mut Request) -> IronResult {
#[derive(Debug,Clone,Deserialize)]
struct SetPassword {
- current: String,
+ // current: String,
password: String,
}
@@ -385,7 +385,7 @@ fn set_password(req: &mut Request) -> IronResult {
let db = state.pool.get().or(Err(MnmlHttpError::DbError))?;
let mut tx = db.transaction().or(Err(MnmlHttpError::DbError))?;
- let token = account::set_password(&mut tx, a.id, ¶ms.current, ¶ms.password)?;
+ let token = account::set_password(&mut tx, a.id, ¶ms.password)?;
tx.commit().or(Err(MnmlHttpError::ServerError))?;
diff --git a/server/src/mail.rs b/server/src/mail.rs
index d5083021..8f3b351f 100644
--- a/server/src/mail.rs
+++ b/server/src/mail.rs
@@ -42,10 +42,10 @@ pub enum Mail {
fn recover(email: &String, name: &String, token: &String) -> SendableEmail {
let body = format!("{:},
the link below will recover your account.
-please change your password immediately in the account page.
-this link will expire in 48 hours or once used.
+please change your password immediately in the account page
+as this link will expire in 48 hours or once used.
-http://mnml.gg/api/account/recover?recover_token={:}
+https://mnml.gg/api/account/recover?recover_token={:}
glhf
--mnml", name, token);
@@ -63,7 +63,7 @@ glhf
fn confirm(email: &String, name: &String, token: &String) -> SendableEmail {
let confirm_body = format!("{:},
please click the link below to confirm your email
-http://mnml.gg/api/account/email/confirm?confirm_token={:}
+https://mnml.gg/api/account/email/confirm?confirm_token={:}
glhf
--mnml", name, token);
diff --git a/server/src/pg.rs b/server/src/pg.rs
index 97444249..995c727b 100644
--- a/server/src/pg.rs
+++ b/server/src/pg.rs
@@ -695,11 +695,17 @@ pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result Result {
- let bot = bot_player();
+ let mut bot = bot_player();
let bot_id = bot.id;
// generate imgs for the client to see
- for c in bot.constructs.iter() {
+ for c in bot.constructs.iter_mut() {
+
+ // smash these nubs
+ c.green_life.force(64);
+ c.red_life.force(0);
+ c.blue_life.force(0);
+
img::shapes_write(c.img)?;
}
@@ -709,6 +715,7 @@ pub fn instance_demo(account: &Account) -> Result {
let player = anon_player(account.id);
+ // smash these noobs
for c in player.constructs.iter() {
img::shapes_write(c.img)?;
}
diff --git a/server/src/rpc.rs b/server/src/rpc.rs
index 7ab789f1..9ffe3bdc 100644
--- a/server/src/rpc.rs
+++ b/server/src/rpc.rs
@@ -2,7 +2,6 @@ use mnml_core::item::ItemInfoCtr;
use mnml_core::instance::ChatState;
use std::collections::HashMap;
-use std::time::{Instant};
use std::thread::{spawn};
use std::str;
@@ -23,7 +22,7 @@ use account;
use events::{Event};
use user_anonymous::{Anonymous};
-use user_authenticated::{Authorised};
+use user_authenticated::{Authenticated};
use mnml_core::construct::{Construct};
use mnml_core::game::{Game};
@@ -37,7 +36,7 @@ use mnml_core::instance::{Instance};
use mtx;
use mail::Email;
-use pg::{Db};
+
use pg::{PgPool};
use http::{AUTH_CLEAR, TOKEN_HEADER};
@@ -63,6 +62,7 @@ pub enum RpcMessage {
Pong(()),
StartTutorial(()),
+ PromptRegister(()),
QueueRequested(()),
QueueJoined(()),
@@ -126,9 +126,9 @@ pub enum RpcRequest {
}
pub trait User {
- fn receive(&mut self, data: Vec, db: &Db, begin: Instant, events: &CbSender, stripe: &StripeClient) -> Result;
- fn connected(&mut self, db: &Db, events: &CbSender, ws: &CbSender) -> Result<(), Error>;
- fn send(&mut self, msg: RpcMessage, events: &CbSender, ws: &CbSender) -> Result<(), Error>;
+ fn receive(&mut self, data: Vec, stripe: &StripeClient) -> Result;
+ fn connected(&mut self) -> Result<(), Error>;
+ fn send(&mut self, msg: RpcMessage) -> Result<(), Error>;
}
struct Connection {
@@ -165,20 +165,16 @@ impl Connection {
// when it encounters errors
impl Handler for Connection {
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
- let db = self.pool.get().unwrap();
- self.user.connected(&db, &self.events, &self.ws).unwrap();
+ self.user.connected().unwrap();
Ok(())
}
fn on_message(&mut self, msg: Message) -> ws::Result<()> {
match msg {
Message::Binary(msg) => {
- let begin = Instant::now();
- let db_connection = self.pool.get().unwrap();
-
- match self.user.receive(msg, &db_connection, begin, &self.events, &self.stripe) {
+ match self.user.receive(msg, &self.stripe) {
Ok(msg) => {
- self.user.send(msg, &self.events, &self.ws).unwrap();
+ self.user.send(msg).unwrap();
},
Err(e) => {
warn!("{:?}", e);
@@ -220,7 +216,7 @@ impl Handler for Connection {
if cookie.name() == TOKEN_HEADER {
let db = self.pool.get().unwrap();
match account::from_token(&db, &cookie.value().to_string()) {
- Ok(a) => self.user = Box::new(Authorised { id: a.id, account: a }),
+ Ok(a) => self.user = Box::new(Authenticated::new(a, self.ws.clone(), self.events.clone(), self.pool.clone())),
Err(_) => return unauth(),
}
}
@@ -268,11 +264,11 @@ pub fn start(pool: PgPool, events_tx: CbSender, stripe: StripeClient) {
DeflateHandler::new(
Connection {
id,
- ws: tx,
+ ws: tx.clone(),
pool: pool.clone(),
stripe: stripe.clone(),
events: events_tx.clone(),
- user: Box::new(Anonymous { id, account: anon_account, game: None, instance: None })
+ user: Box::new(Anonymous::new(anon_account, tx))
}
)
})
diff --git a/server/src/user_anonymous.rs b/server/src/user_anonymous.rs
index a24d9911..213d22a5 100644
--- a/server/src/user_anonymous.rs
+++ b/server/src/user_anonymous.rs
@@ -1,4 +1,3 @@
-use std::time::Instant;
use uuid::Uuid;
use failure::Error;
@@ -9,11 +8,8 @@ use crossbeam_channel::{Sender as CbSender};
use serde_cbor::{from_slice};
use stripe::{Client as StripeClient};
-
use account::{Account};
-use pg::{Db};
use pg;
-use events::{Event};
use rpc::{RpcMessage, RpcRequest, User};
use mnml_core::game::Game;
@@ -26,10 +22,24 @@ pub struct Anonymous {
pub id: Uuid,
pub instance: Option,
pub game: Option,
+
+ ws: CbSender,
+}
+
+impl Anonymous {
+ pub fn new(account: Account, ws: CbSender) -> Anonymous {
+ Anonymous {
+ id: account.id,
+ account,
+ ws,
+ instance: None,
+ game: None,
+ }
+ }
}
impl User for Anonymous {
- fn send(&mut self, msg: RpcMessage, _events: &CbSender, ws: &CbSender) -> Result<(), Error> {
+ fn send(&mut self, msg: RpcMessage) -> Result<(), Error> {
// if the user queries the state of something
// we tell events to push updates to them
match msg {
@@ -40,21 +50,21 @@ impl User for Anonymous {
_ => (),
};
- ws.send(msg)?;
+ self.ws.send(msg)?;
Ok(())
}
- fn connected(&mut self, _db: &Db, events: &CbSender, ws: &CbSender) -> Result<(), Error> {
+ fn connected(&mut self) -> Result<(), Error> {
info!("anonymous connection");
- self.send(RpcMessage::AccountState(self.account.clone()), events, ws)?;
- self.send(RpcMessage::StartTutorial(()), events, ws)?;
+ self.ws.send(RpcMessage::AccountState(self.account.clone()))?;
+ self.ws.send(RpcMessage::StartTutorial(()))?;
Ok(())
}
- fn receive(&mut self, data: Vec, _db: &Db, _begin: Instant, _events: &CbSender, _stripe: &StripeClient) -> Result {
+ fn receive(&mut self, data: Vec, _stripe: &StripeClient) -> Result {
match from_slice::(&data) {
Ok(v) => {
let get_instance = || {
@@ -139,6 +149,10 @@ impl User for Anonymous {
game = game.resolve_phase_start();
}
+ if game.finished() {
+ self.ws.send(RpcMessage::PromptRegister(()))?;
+ }
+
Ok(RpcMessage::GameState(game))
},
diff --git a/server/src/user_authenticated.rs b/server/src/user_authenticated.rs
index 3cf25be8..23d0c69d 100644
--- a/server/src/user_authenticated.rs
+++ b/server/src/user_authenticated.rs
@@ -37,72 +37,90 @@ use events::{Event};
use mtx;
use mail;
use payments;
-use pg::{Db};
+use pg::{PgPool};
use rpc::{RpcMessage, RpcRequest, User};
#[derive(Debug,Clone)]
-pub struct Authorised {
+pub struct Authenticated {
pub account: Account,
- pub id: Uuid
+ pub id: Uuid,
+
+ events: CbSender,
+ ws: CbSender,
+ pool: PgPool,
}
-impl User for Authorised {
- fn send(&mut self, msg: RpcMessage, events: &CbSender, ws: &CbSender) -> Result<(), Error> {
+impl Authenticated {
+ pub fn new(account: Account, ws: CbSender, events: CbSender, pool: PgPool) -> Authenticated {
+ Authenticated {
+ id: account.id,
+ account,
+ ws,
+ events,
+ pool,
+ }
+ }
+}
+
+
+impl User for Authenticated {
+ fn send(&mut self, msg: RpcMessage) -> Result<(), Error> {
// if the user queries the state of something
// we tell events to push updates to them
match msg {
RpcMessage::AccountState(ref v) => {
- events.send(Event::Subscribe(self.id, v.id))?
+ self.events.send(Event::Subscribe(self.id, v.id))?
},
RpcMessage::GameState(ref v) =>
- events.send(Event::Subscribe(self.id, v.id))?,
+ self.events.send(Event::Subscribe(self.id, v.id))?,
RpcMessage::InstanceState(ref v) =>
- events.send(Event::Subscribe(self.id, v.id))?,
+ self.events.send(Event::Subscribe(self.id, v.id))?,
_ => (),
};
- ws.send(msg)?;
+ self.ws.send(msg)?;
Ok(())
}
- fn connected(&mut self, db: &Db, events: &CbSender, ws: &CbSender) -> Result<(), Error> {
+ fn connected(&mut self) -> Result<(), Error> {
info!("authenticated connection account={:?}", self.account);
let a = &self.account;
- ws.send(RpcMessage::AccountAuthenticated(a.clone()))?;
+ self.ws.send(RpcMessage::AccountAuthenticated(a.clone()))?;
// tell events we have connected
- events.send(Event::Connect(self.id, a.clone(), ws.clone()))?;
+ self.events.send(Event::Connect(self.id, a.clone(), self.ws.clone()))?;
- ws.send(RpcMessage::AccountState(a.clone()))?;
- events.send(Event::Subscribe(self.id, a.id))?;
+ self.ws.send(RpcMessage::AccountState(a.clone()))?;
+ self.events.send(Event::Subscribe(self.id, a.id))?;
// check if they have an image that needs to be generated
account::img_check(&a)?;
+ let db = self.pool.get()?;
let mut tx = db.transaction()?;
// send account constructs
let account_constructs = account::constructs(&mut tx, &a)?;
- ws.send(RpcMessage::AccountConstructs(account_constructs))?;
+ self.ws.send(RpcMessage::AccountConstructs(account_constructs))?;
// get account instances
// and send them to the client
let account_instances = account::account_instances(&mut tx, &a)?;
- ws.send(RpcMessage::AccountInstances(account_instances))?;
+ self.ws.send(RpcMessage::AccountInstances(account_instances))?;
let shop = mtx::account_shop(&mut tx, &a)?;
- ws.send(RpcMessage::AccountShop(shop))?;
+ self.ws.send(RpcMessage::AccountShop(shop))?;
let team = account::team(&mut tx, &a)?;
- ws.send(RpcMessage::AccountTeam(team))?;
+ self.ws.send(RpcMessage::AccountTeam(team))?;
let wheel = account::chat_wheel(&db, a.id)?;
- ws.send(RpcMessage::ChatWheel(wheel))?;
+ self.ws.send(RpcMessage::ChatWheel(wheel))?;
if let Some(instance) = account::tutorial(&mut tx, &a)? {
- ws.send(RpcMessage::InstanceState(instance))?;
+ self.ws.send(RpcMessage::InstanceState(instance))?;
}
// tx should do nothing
@@ -111,8 +129,11 @@ impl User for Authorised {
Ok(())
}
- fn receive(&mut self, data: Vec, db: &Db, begin: Instant, events: &CbSender, stripe: &StripeClient) -> Result {
+ fn receive(&mut self, data: Vec, stripe: &StripeClient) -> Result {
// cast the msg to this type to receive method name
+ let begin = Instant::now();
+ let db = self.pool.get()?;
+
match from_slice::(&data) {
Ok(v) => {
let request = v.clone();
@@ -123,19 +144,19 @@ impl User for Authorised {
return Ok(RpcMessage::GameState(anim_test_game(skill))),
RpcRequest::InstanceQueue {} => {
- events.send(Event::Queue(self.id))?;
+ self.events.send(Event::Queue(self.id))?;
Ok(RpcMessage::QueueRequested(()))
},
RpcRequest::InstanceInvite {} => {
- events.send(Event::Invite(self.id))?;
+ self.events.send(Event::Invite(self.id))?;
Ok(RpcMessage::InviteRequested(()))
},
RpcRequest::InstanceJoin { code } => {
- events.send(Event::Join(self.id, code))?;
+ self.events.send(Event::Join(self.id, code))?;
Ok(RpcMessage::Joining(()))
},
RpcRequest::InstanceLeave {} => {
- events.send(Event::Leave(self.id))?;
+ self.events.send(Event::Leave(self.id))?;
Ok(RpcMessage::Processing(()))
},
@@ -147,7 +168,7 @@ impl User for Authorised {
let wheel = account::chat_wheel(&db, self.account.id)?;
if let Some(c) = wheel.get(index) {
- events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
+ self.events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
} else {
return Err(err_msg("invalid chat index"));
}
@@ -172,7 +193,7 @@ impl User for Authorised {
Ok(RpcMessage::EmailState(mail::select_account(&db, self.account.id)?)),
RpcRequest::SubscriptionState {} =>
- Ok(RpcMessage::SubscriptionState(payments::account_subscription(db, stripe, &self.account)?)),
+ Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, stripe, &self.account)?)),
// RpcRequest::AccountShop {} =>
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
diff --git a/studios/package.json b/studios/package.json
index d7abb0fd..4d90c4c3 100644
--- a/studios/package.json
+++ b/studios/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-studios",
- "version": "1.11.2",
+ "version": "1.12.0",
"description": "",
"main": "index.js",
"scripts": {