Merge branch 'release/1.12.0'
This commit is contained in:
commit
d1606e9117
29
WORKLOG.md
29
WORKLOG.md
@ -3,32 +3,16 @@
|
||||
|
||||
_ntr_
|
||||
* can't reset password without knowing password =\
|
||||
* change cooldowns to delay & recharge
|
||||
- delay is cooldown before skill can first be used
|
||||
- recharge is cooldown after using skill
|
||||
- every x speed reduces delay of skills
|
||||
|
||||
* audio
|
||||
* animation effects
|
||||
* vbox combine / buy / equip etc
|
||||
* background music
|
||||
* effects rework
|
||||
|
||||
Siphon =
|
||||
[
|
||||
DamageBlue(50%),
|
||||
Apply(
|
||||
Siphon(2T)
|
||||
- Siphoning(2T)
|
||||
),
|
||||
]
|
||||
|
||||
Hexagon Set
|
||||
- Pick Colour
|
||||
- Random Walk
|
||||
- Draw hex
|
||||
- Increase intensity for each visit
|
||||
|
||||
_mashy_
|
||||
* combat text
|
||||
- last 3-4 text events (damage / heal / disable etc)
|
||||
|
||||
* rebalance
|
||||
* speed specs
|
||||
* life specs
|
||||
@ -111,6 +95,11 @@ _tba_
|
||||
* treats
|
||||
* client animation bpm
|
||||
* background colour changes depending on time of day
|
||||
Hexagon Set
|
||||
- Pick Colour
|
||||
- Random Walk
|
||||
- Draw hex
|
||||
- Increase intensity for each visit
|
||||
|
||||
# Mechanics
|
||||
* 10d chaos maths, not rock paper scissors
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.11.2",
|
||||
"version": "1.12.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -100,6 +100,12 @@ section {
|
||||
}
|
||||
}
|
||||
|
||||
.block-text {
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 2em;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.11.2",
|
||||
"version": "1.12.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -19,8 +19,8 @@ const addState = connect(
|
||||
} = state;
|
||||
|
||||
|
||||
function sendSetPassword(current, password) {
|
||||
postData('/account/password', { current, password })
|
||||
function sendSetPassword(password) {
|
||||
postData('/account/password', { password })
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.error) return errorToast(data.error);
|
||||
@ -74,7 +74,7 @@ class AccountStatus extends Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
passwordState: { current: '', password: '', confirm: ''},
|
||||
passwordState: { password: '', confirm: ''},
|
||||
emailState: null,
|
||||
unsubState: false,
|
||||
};
|
||||
@ -105,8 +105,8 @@ class AccountStatus extends Component {
|
||||
passwordState.password === passwordState.confirm;
|
||||
|
||||
const setPasswordDisabled = () => {
|
||||
const { current, password, confirm } = passwordState;
|
||||
return !(passwordsEqual() && password && current && confirm);
|
||||
const { password, confirm } = passwordState;
|
||||
return !(passwordsEqual() && password && confirm);
|
||||
}
|
||||
|
||||
const tlClick = e => {
|
||||
@ -173,15 +173,7 @@ class AccountStatus extends Component {
|
||||
</div>
|
||||
<div>
|
||||
<h3>Password</h3>
|
||||
<label for="current">Password:</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
name="current"
|
||||
value={passwordState.current}
|
||||
onInput={linkState(this, 'passwordState.current')}
|
||||
placeholder="current"
|
||||
/>
|
||||
<label for="current">Set Password:</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
@ -202,7 +194,7 @@ class AccountStatus extends Component {
|
||||
/>
|
||||
<button
|
||||
disabled={setPasswordDisabled()}
|
||||
onClick={() => sendSetPassword(passwordState.current, passwordState.password)}>
|
||||
onClick={() => sendSetPassword(passwordState.password)}>
|
||||
Set Password
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -14,6 +14,7 @@ const addState = connect(
|
||||
const {
|
||||
ws,
|
||||
account,
|
||||
tutorial,
|
||||
} = state;
|
||||
|
||||
function sendInstancePractice() {
|
||||
@ -21,6 +22,7 @@ const addState = connect(
|
||||
}
|
||||
|
||||
return {
|
||||
promptRegister: tutorial === 99, // see events
|
||||
account,
|
||||
sendInstancePractice,
|
||||
};
|
||||
@ -30,6 +32,7 @@ const addState = connect(
|
||||
function Play(args) {
|
||||
const {
|
||||
account,
|
||||
promptRegister,
|
||||
sendInstancePractice,
|
||||
} = args;
|
||||
|
||||
@ -47,6 +50,17 @@ function Play(args) {
|
||||
);
|
||||
|
||||
const list = () => {
|
||||
|
||||
if (promptRegister) {
|
||||
return (
|
||||
<div class='block-text'>
|
||||
<p><b>You just won your first round of MNML.</b></p>
|
||||
<p>Register below to play a real Bo5 against other players, play a practice round, customise your team & more...</p>
|
||||
<p>glhf</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class='list play'>
|
||||
<figure>
|
||||
|
||||
@ -9,6 +9,7 @@ const addState = connect(
|
||||
ws,
|
||||
game,
|
||||
account,
|
||||
authenticated,
|
||||
chatShow,
|
||||
animating,
|
||||
} = state;
|
||||
@ -33,6 +34,7 @@ const addState = connect(
|
||||
return {
|
||||
game,
|
||||
account,
|
||||
authenticated,
|
||||
chatShow,
|
||||
sendAbandon,
|
||||
sendGameSkillClear,
|
||||
@ -65,6 +67,7 @@ function GameCtrlBtns(args) {
|
||||
animating,
|
||||
account,
|
||||
chatShow,
|
||||
authenticated,
|
||||
|
||||
getInstanceState,
|
||||
sendGameSkillClear,
|
||||
@ -77,7 +80,9 @@ function GameCtrlBtns(args) {
|
||||
const finished = game.phase === 'Finished';
|
||||
|
||||
function quitClick() {
|
||||
getInstanceState();
|
||||
if (authenticated) {
|
||||
getInstanceState();
|
||||
}
|
||||
quit();
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ const addState = connect(
|
||||
ws,
|
||||
game,
|
||||
animating,
|
||||
authenticated,
|
||||
account,
|
||||
} = state;
|
||||
|
||||
@ -27,6 +28,7 @@ const addState = connect(
|
||||
return {
|
||||
game,
|
||||
account,
|
||||
authenticated,
|
||||
|
||||
sendAbandon,
|
||||
sendDraw,
|
||||
@ -50,6 +52,7 @@ function GameCtrlTopBtns(args) {
|
||||
const {
|
||||
game,
|
||||
account,
|
||||
authenticated,
|
||||
|
||||
leave,
|
||||
sendAbandon,
|
||||
@ -82,6 +85,11 @@ function GameCtrlTopBtns(args) {
|
||||
setTimeout(() => this.setState({ concedeState: false }), 2000);
|
||||
};
|
||||
|
||||
const authBtn = btn => {
|
||||
if (authenticated) return btn;
|
||||
return <button disabled>-</button>
|
||||
}
|
||||
|
||||
const abandonClasses = `abandon ${abandonState ? 'confirming' : ''}`;
|
||||
const abandonText = abandonState ? 'Confirm' : 'Abandon';
|
||||
const abandonAction = abandonState ? sendAbandon : abandonStateTrue;
|
||||
@ -102,9 +110,9 @@ function GameCtrlTopBtns(args) {
|
||||
|
||||
return (
|
||||
<div class="instance-ctrl-btns">
|
||||
{abandonBtn}
|
||||
{concedeBtn}
|
||||
{drawBtn}
|
||||
{authBtn(abandonBtn)}
|
||||
{authBtn(concedeBtn)}
|
||||
{authBtn(drawBtn)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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 = <button class={abandonClasses} disabled={finished} onClick={abandonAction}>{abandonText}</button>;
|
||||
const leaveBtn = <button class='abandon confirming' onClick={() => leave(tutorial)}>Leave</button>;
|
||||
|
||||
const finalBtn = () => {
|
||||
// disable for tutorial mode
|
||||
if (!authenticated) return <button disabled='true'>-</button>;
|
||||
if (finished) return leaveBtn;
|
||||
return abandonBtn;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="instance-ctrl-btns">
|
||||
{finished ? leaveBtn : abandonBtn}
|
||||
{finalBtn()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -232,7 +232,6 @@ function Play(args) {
|
||||
<div>
|
||||
Join our Discord server to find opponents and talk to the devs. <br />
|
||||
Message <b>@ntr</b> or <b>@mashy</b> for some credits to get started.<br />
|
||||
<a href='https://www.youtube.com/watch?v=VtZLlkpJuS8'>Tutorial Playthrough on YouTube</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
|
||||
@ -96,7 +96,7 @@ function genItemInfo(item, itemInfo, player) {
|
||||
itemSourceInfo = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
|
||||
}
|
||||
|
||||
const cooldown = isSkill && fullInfo.cooldown ? <div>{fullInfo.cooldown} Turn delay</div> : null;
|
||||
const cooldown = isSkill && fullInfo.cooldown ? <div>{fullInfo.delay} turn delay, {fullInfo.cooldown} turn cooldown</div> : null;
|
||||
|
||||
const speed = isSkill
|
||||
? <div> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </div>
|
||||
|
||||
@ -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 <Login />;
|
||||
@ -45,4 +63,4 @@ function Welcome() {
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = Welcome;
|
||||
module.exports = addState(Welcome);
|
||||
|
||||
@ -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.',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -301,6 +301,7 @@ function createSocket(events) {
|
||||
// Joining: () => events.notify('Searching for instance...'),
|
||||
|
||||
StartTutorial: () => events.startTutorial(),
|
||||
PromptRegister: () => events.promptRegister(),
|
||||
|
||||
Processing: () => true,
|
||||
Error: errHandler,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml_core"
|
||||
version = "1.11.2"
|
||||
version = "1.12.0"
|
||||
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -104,7 +104,6 @@ impl Game {
|
||||
// let player_description = player.constructs.iter().map(|c| c.name.clone()).collect::<Vec<String>>().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();
|
||||
|
||||
@ -1362,6 +1362,7 @@ pub struct ItemInfo {
|
||||
pub values: Option<SpecValues>,
|
||||
pub skill: bool,
|
||||
pub speed: Option<usize>,
|
||||
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::<Vec<ItemInfo>>();
|
||||
|
||||
|
||||
@ -65,7 +65,9 @@ pub struct Player {
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(account: Uuid, img: Option<Uuid>, name: &String, constructs: Vec<Construct>) -> Player {
|
||||
pub fn new(account: Uuid, img: Option<Uuid>, name: &String, mut constructs: Vec<Construct>) -> Player {
|
||||
constructs.sort_unstable_by_key(|c| c.id);
|
||||
|
||||
Player {
|
||||
id: account,
|
||||
img,
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-ops",
|
||||
"version": "1.11.2",
|
||||
"version": "1.12.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml"
|
||||
version = "1.11.2"
|
||||
version = "1.12.0"
|
||||
authors = ["ntr <ntr@smokestack.io>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -213,42 +213,42 @@ pub fn new_img(tx: &mut Transaction, id: Uuid) -> Result<Account, Error> {
|
||||
Account::try_from(row)
|
||||
}
|
||||
|
||||
pub fn set_password(tx: &mut Transaction, id: Uuid, current: &String, password: &String) -> Result<String, MnmlHttpError> {
|
||||
pub fn set_password(tx: &mut Transaction, id: Uuid, password: &String) -> Result<String, MnmlHttpError> {
|
||||
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)?;
|
||||
|
||||
|
||||
@ -369,7 +369,7 @@ fn recover(req: &mut Request) -> IronResult<Response> {
|
||||
|
||||
#[derive(Debug,Clone,Deserialize)]
|
||||
struct SetPassword {
|
||||
current: String,
|
||||
// current: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
@ -385,7 +385,7 @@ fn set_password(req: &mut Request) -> IronResult<Response> {
|
||||
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))?;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -695,11 +695,17 @@ pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result<Inst
|
||||
}
|
||||
|
||||
pub fn instance_demo(account: &Account) -> Result<Instance, Error> {
|
||||
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<Instance, Error> {
|
||||
|
||||
let player = anon_player(account.id);
|
||||
|
||||
// smash these noobs
|
||||
for c in player.constructs.iter() {
|
||||
img::shapes_write(c.img)?;
|
||||
}
|
||||
|
||||
@ -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<u8>, db: &Db, begin: Instant, events: &CbSender<Event>, stripe: &StripeClient) -> Result<RpcMessage, Error>;
|
||||
fn connected(&mut self, db: &Db, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error>;
|
||||
fn send(&mut self, msg: RpcMessage, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error>;
|
||||
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error>;
|
||||
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<Event>, 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))
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@ -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<Instance>,
|
||||
pub game: Option<Game>,
|
||||
|
||||
ws: CbSender<RpcMessage>,
|
||||
}
|
||||
|
||||
impl Anonymous {
|
||||
pub fn new(account: Account, ws: CbSender<RpcMessage>) -> Anonymous {
|
||||
Anonymous {
|
||||
id: account.id,
|
||||
account,
|
||||
ws,
|
||||
instance: None,
|
||||
game: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl User for Anonymous {
|
||||
fn send(&mut self, msg: RpcMessage, _events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> 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<Event>, ws: &CbSender<RpcMessage>) -> 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<u8>, _db: &Db, _begin: Instant, _events: &CbSender<Event>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||
fn receive(&mut self, data: Vec<u8>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||
match from_slice::<RpcRequest>(&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))
|
||||
},
|
||||
|
||||
|
||||
@ -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<Event>,
|
||||
ws: CbSender<RpcMessage>,
|
||||
pool: PgPool,
|
||||
}
|
||||
|
||||
impl User for Authorised {
|
||||
fn send(&mut self, msg: RpcMessage, events: &CbSender<Event>, ws: &CbSender<RpcMessage>) -> Result<(), Error> {
|
||||
impl Authenticated {
|
||||
pub fn new(account: Account, ws: CbSender<RpcMessage>, events: CbSender<Event>, 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<Event>, ws: &CbSender<RpcMessage>) -> 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<u8>, db: &Db, begin: Instant, events: &CbSender<Event>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||
// cast the msg to this type to receive method name
|
||||
let begin = Instant::now();
|
||||
let db = self.pool.get()?;
|
||||
|
||||
match from_slice::<RpcRequest>(&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)?)),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-studios",
|
||||
"version": "1.11.2",
|
||||
"version": "1.12.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user