Merge tag '1.13.0' into develop
1.13.0
This commit is contained in:
commit
40f3bb5be6
@ -5,6 +5,9 @@ _ntr_
|
||||
* can't reset password without knowing password =\
|
||||
* hard reload client on version change
|
||||
|
||||
decay reflected not applied
|
||||
black out timer when game finished
|
||||
|
||||
* audio
|
||||
* animation effects
|
||||
* vbox combine / buy / equip etc
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.12.4",
|
||||
"version": "1.13.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -27,6 +27,3 @@ ssh -q "$TARGET" ls -lah "$CLIENT_DIST_DIR"
|
||||
|
||||
echo "restarting mnml service"
|
||||
ssh -q -t "$TARGET" sudo service mnml restart && sleep 1 && systemctl --no-pager status mnml
|
||||
|
||||
echo "restarting nginx service"
|
||||
ssh -q -t "$TARGET" sudo service nginx restart && sleep 1 && systemctl --no-pager status nginx
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.12.4",
|
||||
"version": "1.13.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -45,7 +45,7 @@ function Controls(args) {
|
||||
const now = animating ? zero : Date.now();
|
||||
const end = Date.parse(game.phase_end);
|
||||
|
||||
const timerPct = game.phase_end
|
||||
const timerPct = game.phase_end || !game.phase == 'Finished'
|
||||
? ((now - zero) / (end - zero) * 100)
|
||||
: 100;
|
||||
|
||||
|
||||
@ -316,6 +316,7 @@ function createSocket(events) {
|
||||
case 'no constructs selected': return events.errorPrompt('select_constructs');
|
||||
case 'node requirements not met': return events.errorPrompt('complete_nodes');
|
||||
case 'construct at max skills (4)': return events.errorPrompt('max_skills');
|
||||
case 'instance missing': return window.location.reload();
|
||||
|
||||
default: return errorToast(error);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml_core"
|
||||
version = "1.12.4"
|
||||
version = "1.13.0"
|
||||
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -65,7 +65,7 @@ impl ConstructSkill {
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum EffectMeta {
|
||||
CastOnHit(Skill), // maybe needs source/target
|
||||
CastTick { source: Uuid, target: Uuid, skill: Skill, speed: usize, amount: usize },
|
||||
CastTick { source: Uuid, target: Uuid, skill: Skill, speed: usize, amount: usize, id: Uuid },
|
||||
AddedDamage(usize),
|
||||
Multiplier(usize),
|
||||
}
|
||||
@ -100,12 +100,19 @@ impl ConstructEffect {
|
||||
|
||||
pub fn get_skill(&self) -> Option<Skill> {
|
||||
match self.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill, speed: _, amount: _ }) => Some(skill),
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill, speed: _, amount: _, id: _ }) => Some(skill),
|
||||
Some(EffectMeta::CastOnHit(s)) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn get_tick_id(&self) -> Option<Uuid> {
|
||||
match self.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount: _, id }) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
@ -561,7 +568,7 @@ impl Construct {
|
||||
fn tick_damage(&self, effect: Effect) -> usize {
|
||||
match self.effects.iter().find_map(|ce| match ce.effect == effect {
|
||||
true => match ce.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount }) => Some(amount),
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount, id: _ }) => Some(amount),
|
||||
_ => None,
|
||||
},
|
||||
false => None,
|
||||
@ -1033,8 +1040,6 @@ impl Construct {
|
||||
}
|
||||
|
||||
pub fn damage_trigger_casts(&mut self, cast: &Cast, event: &Event) -> Vec<Cast> {
|
||||
if self.is_ko() { return vec![] }
|
||||
|
||||
match event {
|
||||
Event::Damage { construct: _, colour, amount: _, mitigation: _, display: _ } => {
|
||||
let mut casts = vec![];
|
||||
@ -1049,6 +1054,9 @@ impl Construct {
|
||||
};
|
||||
}
|
||||
|
||||
// electrocute is a special case, so we only return after we check it when ko
|
||||
if self.is_ko() { return casts }
|
||||
|
||||
if self.affected(Effect::Absorb) {
|
||||
let ConstructEffect { effect: _, duration: _, meta } =
|
||||
self.effects.iter().find(|e| e.effect == Effect::Absorb).unwrap();
|
||||
|
||||
@ -81,7 +81,7 @@ impl Effect {
|
||||
Skill::CounterAttackPlus,
|
||||
Skill::CounterAttackPlusPlus,
|
||||
].contains(&skill),
|
||||
|
||||
|
||||
// these provide immunity for the ticks
|
||||
// the base skills will still resolve
|
||||
// but they have early return checks
|
||||
@ -125,6 +125,12 @@ impl Effect {
|
||||
return false;
|
||||
}
|
||||
|
||||
// electrocute always goes off baybee
|
||||
// even if you are stunned particularly
|
||||
if [Skill::Electrocute, Skill::ElectrocutePlus, Skill::ElectrocutePlusPlus].contains(&skill) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match self {
|
||||
Effect::Stun => true,
|
||||
Effect::Banish => true,
|
||||
|
||||
170
core/src/game.rs
170
core/src/game.rs
@ -428,8 +428,12 @@ impl Game {
|
||||
.cloned()
|
||||
.filter_map(|e| e.meta)
|
||||
.filter_map(move |m| match m {
|
||||
EffectMeta::CastTick { source, target, skill, speed, amount: _ } =>
|
||||
Some(Cast::new(source, c.account, target, skill).set_speed(speed)),
|
||||
EffectMeta::CastTick { source, target, skill, speed, amount: _, id } =>
|
||||
Some(
|
||||
Cast::new(source, c.account, target, skill)
|
||||
.set_speed(speed)
|
||||
.set_id(id)
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
)
|
||||
@ -506,6 +510,20 @@ impl Game {
|
||||
fn resolve(&mut self, cast: Cast) -> &mut Game {
|
||||
if self.finished() { return self }
|
||||
|
||||
// match tick skills with the effect on the target
|
||||
// if no match is found the effect must have been removed during this turn
|
||||
// and the skill should no longer resolve
|
||||
if cast.skill.is_tick() {
|
||||
let effect_match = self.construct(cast.target).effects.iter()
|
||||
.filter_map(|ce| ce.get_tick_id())
|
||||
.find(|id| cast.id == *id)
|
||||
.is_some();
|
||||
|
||||
if !effect_match {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
// If the skill is disabled for source nothing else will happen
|
||||
if let Some(effects) = self.construct(cast.source).disabled(cast.skill) {
|
||||
self.add_resolution(&cast, &Event::Disable { construct: cast.source, effects });
|
||||
@ -1054,6 +1072,7 @@ mod tests {
|
||||
.learn(Skill::Block)
|
||||
.learn(Skill::Counter)
|
||||
.learn(Skill::Siphon)
|
||||
.learn(Skill::Purify)
|
||||
.learn(Skill::Amplify)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Ruin)
|
||||
@ -1069,6 +1088,7 @@ mod tests {
|
||||
.learn(Skill::Block)
|
||||
.learn(Skill::Counter)
|
||||
.learn(Skill::Siphon)
|
||||
.learn(Skill::Purify)
|
||||
.learn(Skill::Amplify)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block);
|
||||
@ -1874,85 +1894,6 @@ mod tests {
|
||||
return;
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn tick_removal_test() {
|
||||
// let mut game = create_test_game();
|
||||
|
||||
// let x_player = game.players[0].clone();
|
||||
// let y_player = game.players[1].clone();
|
||||
|
||||
// let x_construct = x_player.constructs[0].clone();
|
||||
// let y_construct = y_player.constructs[0].clone();
|
||||
|
||||
// // make the purify construct super fast so it beats out decay
|
||||
// game.construct_by_id(y_construct.id).unwrap().speed.force(10000000);
|
||||
|
||||
// game.construct_by_id(x_construct.id).unwrap().learn_mut(Skill::Decay);
|
||||
// while game.construct_by_id(x_construct.id).unwrap().skill_on_cd(Skill::Decay).is_some() {
|
||||
// game.construct_by_id(x_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// game.construct_by_id(x_construct.id).unwrap().learn_mut(Skill::Siphon);
|
||||
// while game.construct_by_id(x_construct.id).unwrap().skill_on_cd(Skill::Siphon).is_some() {
|
||||
// game.construct_by_id(x_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// game.construct_by_id(y_construct.id).unwrap().learn_mut(Skill::Purify);
|
||||
// while game.construct_by_id(y_construct.id).unwrap().skill_on_cd(Skill::Purify).is_some() {
|
||||
// game.construct_by_id(y_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// // apply buff
|
||||
// game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Decay).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
// assert!(game.construct_by_id(y_construct.id).unwrap().affected(Effect::Decay));
|
||||
|
||||
// let Resolution { source: _, target: _, Resolution, stages: _ } = game.Resolutions.last().unwrap().pop().unwrap();
|
||||
// match Resolution {
|
||||
// Resolution::Damage { amount: _, skill, mitigation: _, colour: _ } => assert_eq!(skill, Skill::DecayTick),
|
||||
// _ => panic!("not decay"),
|
||||
// };
|
||||
|
||||
// game.Resolutions.clear();
|
||||
|
||||
// // remove
|
||||
// game.add_skill(y_player.id, y_construct.id, y_construct.id, Skill::Purify).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
|
||||
// while let Some(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() {
|
||||
// match Resolution {
|
||||
// Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
|
||||
// panic!("{:?} damage Resolution", Resolution),
|
||||
// _ => (),
|
||||
// }
|
||||
// };
|
||||
|
||||
// game.add_skill(y_player.id, x_construct.id, y_construct.id, Skill::Siphon).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
|
||||
// game.Resolutions.clear();
|
||||
|
||||
// game.add_skill(y_player.id, y_construct.id, y_construct.id, Skill::Purify).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
|
||||
// while let Some(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() {
|
||||
// match Resolution {
|
||||
// Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
|
||||
// panic!("{:#?} {:#?} damage Resolution", game.Resolutions, Resolution),
|
||||
// _ => (),
|
||||
// }
|
||||
// };
|
||||
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn upkeep_test() {
|
||||
let mut game = create_2v2_test_game();
|
||||
@ -2269,8 +2210,41 @@ mod tests {
|
||||
|
||||
assert!(effect_events == 2);
|
||||
assert!(electrocute_dmg_events == 1); // second electrocute application deals no damage
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn electrocute_ko_test() {
|
||||
let mut game = create_2v2_test_game();
|
||||
let player_id = game.players[0].id;
|
||||
let source = game.players[0].constructs[0].id;
|
||||
let target = game.players[1].constructs[0].id;
|
||||
|
||||
game.players[1].constructs[0].blue_life.force(0);
|
||||
game.players[1].constructs[0].green_life.force(1);
|
||||
|
||||
game.resolve(Cast::new(source, player_id, target, Skill::Electrify));
|
||||
game.resolve(Cast::new(source, player_id, target, Skill::Blast));
|
||||
|
||||
let last = game.resolutions.len() - 1;
|
||||
let resolutions = &game.resolutions[last];
|
||||
|
||||
// println!("{:#?}", resolutions);
|
||||
|
||||
assert!(resolutions.iter().any(|r| match r.event {
|
||||
Event::Damage { construct, colour, amount, mitigation: _, display: _ } =>
|
||||
r.skill == Skill::Electrocute && construct == source && amount > 0 && colour == Colour::Blue,
|
||||
_ => false,
|
||||
}));
|
||||
|
||||
let effect_events = resolutions.iter().filter(|r| match r.event {
|
||||
Event::Effect { construct, effect, duration: _, display: _ } =>
|
||||
construct == source && effect == Effect::Electrocute,
|
||||
_ => false,
|
||||
}).count();
|
||||
|
||||
// println!("{:?}", effect_events);
|
||||
|
||||
assert!(effect_events == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -2524,4 +2498,38 @@ mod tests {
|
||||
assert_eq!(siphon_tick_dmg, siphon_dmg);
|
||||
assert_eq!(siphon_tick_speed, siphon_speed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tick_removal_test() {
|
||||
let mut game = create_test_game();
|
||||
let player_id = game.players[0].id;
|
||||
let opponent_id = game.players[1].id;
|
||||
let source = game.players[0].constructs[0].id;
|
||||
let target = game.players[1].constructs[0].id;
|
||||
|
||||
game.add_skill(player_id, source, target, Skill::Siphon).unwrap();
|
||||
|
||||
game.player_ready(player_id).unwrap();
|
||||
game.player_ready(opponent_id).unwrap();
|
||||
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
game.add_skill(player_id, source, target, Skill::Purify).unwrap();
|
||||
|
||||
game.player_ready(player_id).unwrap();
|
||||
game.player_ready(opponent_id).unwrap();
|
||||
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
// println!("{:#?}", game.resolutions);
|
||||
|
||||
let last = game.resolutions.len() - 1;
|
||||
let resolutions = &game.resolutions[last];
|
||||
|
||||
// There should be no damage events on the target
|
||||
assert!(resolutions.iter().any(|r| match r.event {
|
||||
Event::Damage { construct: _, colour: _, amount: _, mitigation: _, display: _ } => true,
|
||||
_ => false,
|
||||
}) == false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,15 @@ impl Cast {
|
||||
}
|
||||
}
|
||||
|
||||
// used for ticks to match
|
||||
// a cast with an effect
|
||||
pub fn set_id(self, id: Uuid) -> Cast {
|
||||
Cast {
|
||||
id,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve(self, game: &mut Game) {
|
||||
match self.skill {
|
||||
Skill::Attack => attack(self, game, Attack::Base),
|
||||
@ -729,6 +738,13 @@ impl Skill {
|
||||
|
||||
pub fn ko_castable(&self) -> bool {
|
||||
match self {
|
||||
|
||||
// electrocute always goes off
|
||||
Skill::Electrocute|
|
||||
Skill::ElectrocutePlus |
|
||||
Skill::ElectrocutePlusPlus |
|
||||
|
||||
// ticks happen after death
|
||||
Skill::ElectrocuteTick |
|
||||
Skill::DecayTick |
|
||||
Skill::SiphonTick |
|
||||
@ -1134,7 +1150,7 @@ fn siphon(cast: Cast, game: &mut Game, values: Siphon) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Siphon, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::SiphonTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::SiphonTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
@ -1729,7 +1745,7 @@ fn decay(cast: Cast, game: &mut Game, values: Decay) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Decay, duration: values.decay_duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::DecayTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::DecayTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
@ -1837,10 +1853,10 @@ fn electrocute(cast: Cast, game: &mut Game, values: Electrocute) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Electrocute, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::ElectrocuteTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::ElectrocuteTick, speed: cast.speed, amount }) },
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
if !game.affected(cast.target, Effect::Electrocuted) {
|
||||
game.action(cast,
|
||||
Action::Damage {
|
||||
@ -2362,7 +2378,7 @@ fn triage(cast: Cast, game: &mut Game, values: Triage) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Triage, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::TriageTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::TriageTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-ops",
|
||||
"version": "1.12.4",
|
||||
"version": "1.13.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml"
|
||||
version = "1.12.4"
|
||||
version = "1.13.0"
|
||||
authors = ["ntr <ntr@smokestack.io>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -17,7 +17,7 @@ use rpc::RpcMessage;
|
||||
use warden::{GameEvent};
|
||||
|
||||
pub type EventsTx = Sender<Event>;
|
||||
type Id = Uuid;
|
||||
type Id = usize;
|
||||
|
||||
// this is pretty heavyweight
|
||||
// but it makes the ergonomics easy
|
||||
@ -60,8 +60,13 @@ pub enum Event {
|
||||
ChatClear(Id, Uuid),
|
||||
}
|
||||
|
||||
// id and account are seperate
|
||||
// multiple tabs etc can cause the same account to be connected twice
|
||||
// so even though each client has the same subs etc
|
||||
// they are treated independently
|
||||
struct WsClient {
|
||||
id: Id,
|
||||
account: Uuid,
|
||||
tx: Sender<RpcMessage>,
|
||||
subs: HashSet<Uuid>,
|
||||
chat: Option<(Uuid, String)>,
|
||||
@ -103,7 +108,9 @@ impl Events {
|
||||
Event::Connect(id, account, tx) => {
|
||||
info!("connect id={:?} account={:?}", id, account);
|
||||
|
||||
let client = WsClient { id,
|
||||
let client = WsClient {
|
||||
id,
|
||||
account: account.id,
|
||||
tx,
|
||||
subs: HashSet::new(),
|
||||
pvp: false,
|
||||
@ -163,8 +170,8 @@ impl Events {
|
||||
subs += 1;
|
||||
|
||||
let redacted = match msg {
|
||||
RpcMessage::InstanceState(ref i) => RpcMessage::InstanceState(i.clone().redact(client.id)),
|
||||
RpcMessage::GameState(ref i) => RpcMessage::GameState(i.clone().redact(client.id)),
|
||||
RpcMessage::InstanceState(ref i) => RpcMessage::InstanceState(i.clone().redact(client.account)),
|
||||
RpcMessage::GameState(ref i) => RpcMessage::GameState(i.clone().redact(client.account)),
|
||||
_ => msg.clone(),
|
||||
};
|
||||
|
||||
@ -203,7 +210,7 @@ impl Events {
|
||||
if let Some(opp_req) = match self.clients.iter_mut().find(|(c_id, c)| c.pvp && **c_id != id) {
|
||||
Some((q_id, q)) => {
|
||||
q.pvp = false;
|
||||
Some(PvpRequest { id: *q_id, account: q.id, tx: q.tx.clone() })
|
||||
Some(PvpRequest { id: *q_id, account: q.account, tx: q.tx.clone() })
|
||||
},
|
||||
None => None,
|
||||
} {
|
||||
@ -211,7 +218,7 @@ impl Events {
|
||||
let c = self.clients.get_mut(&id)
|
||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||
|
||||
let player_req = PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() };
|
||||
let player_req = PvpRequest { id: c.id, account: c.account, tx: c.tx.clone() };
|
||||
self.warden.send(GameEvent::Match((opp_req, player_req)))?;
|
||||
|
||||
return Ok(())
|
||||
@ -221,7 +228,7 @@ impl Events {
|
||||
let requester = self.clients.get_mut(&id).unwrap();
|
||||
requester.pvp = true;
|
||||
requester.tx.send(RpcMessage::QueueJoined(()))?;
|
||||
info!("joined game queue id={:?} account={:?}", requester.id, requester.id);
|
||||
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
@ -231,7 +238,7 @@ impl Events {
|
||||
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||
|
||||
let code = names::name().split_whitespace().collect::<Vec<&str>>().join("-");
|
||||
info!("pvp invite request id={:?} account={:?} code={:?}", c.id, c.id, code);
|
||||
info!("pvp invite request id={:?} account={:?} code={:?}", c.id, c.account, code);
|
||||
c.invite = Some(code.clone());
|
||||
c.tx.send(RpcMessage::Invite(code))?;
|
||||
return Ok(());
|
||||
@ -250,10 +257,10 @@ impl Events {
|
||||
Some(ref c) => *c == code,
|
||||
None => false,
|
||||
})
|
||||
.map(|(_id, c)| PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() })
|
||||
.map(|(_id, c)| PvpRequest { id: c.id, account: c.account, tx: c.tx.clone() })
|
||||
.ok_or(format_err!("invite expired code={:?}", code))?;
|
||||
|
||||
let join = PvpRequest { id: c.id, account: c.id, tx: c.tx.clone() };
|
||||
let join = PvpRequest { id: c.id, account: c.account, tx: c.tx.clone() };
|
||||
|
||||
self.warden.send(GameEvent::Match((join, inv)))?;
|
||||
return Ok(());
|
||||
@ -276,7 +283,7 @@ impl Events {
|
||||
|
||||
c.pvp = false;
|
||||
c.tx.send(RpcMessage::QueueLeft(()))?;
|
||||
info!("left game queue id={:?} account={:?}", c.id, c.id);
|
||||
info!("left game queue id={:?} account={:?}", c.id, c.account);
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
@ -307,7 +314,7 @@ impl Events {
|
||||
Some(ref chat) => chat.0 == instance,
|
||||
None => false,
|
||||
})
|
||||
.map(|(_id, c)| (c.id, c.chat.clone().unwrap().1))
|
||||
.map(|(_id, c)| (c.account, c.chat.clone().unwrap().1))
|
||||
.collect();
|
||||
|
||||
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
||||
@ -326,7 +333,7 @@ impl Events {
|
||||
Some(ref chat) => chat.0 == instance,
|
||||
None => false,
|
||||
})
|
||||
.map(|(_id, c)| (c.id, c.chat.clone().unwrap().1))
|
||||
.map(|(_id, c)| (c.account, c.chat.clone().unwrap().1))
|
||||
.collect();
|
||||
|
||||
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
|
||||
|
||||
@ -109,6 +109,7 @@ pub fn start() {
|
||||
#[cfg(unix)]
|
||||
setup_logger().unwrap();
|
||||
dotenv::from_path(Path::new("/etc/mnml/gs.conf")).ok();
|
||||
info!("starting server");
|
||||
|
||||
let pool = pg::create_pool();
|
||||
let http_pool = pool.clone();
|
||||
|
||||
@ -248,8 +248,8 @@ pub fn set(tx: &mut Transaction, account: Uuid, email: &String) -> Result<(Uuid,
|
||||
let existing = tx.query(select_query, &[&id])?;
|
||||
|
||||
let result = match existing.iter().next() {
|
||||
Some(_) => tx.query(insert_query, &[&id, &account, &email, &confirm_token, &recover_token])?,
|
||||
None => tx.query(update_query, &[&email, &confirm_token, &recover_token, &account])?,
|
||||
Some(_) => tx.query(update_query, &[&email, &confirm_token, &recover_token, &account])?,
|
||||
None => tx.query(insert_query, &[&id, &account, &email, &confirm_token, &recover_token])?,
|
||||
};
|
||||
|
||||
match result.iter().next() {
|
||||
|
||||
@ -17,6 +17,8 @@ use crossbeam_channel::{unbounded, Sender as CbSender};
|
||||
use ws::{Builder, CloseCode, Message, Handler, Request, Response, Settings, Sender as WsSender};
|
||||
use ws::deflate::DeflateHandler;
|
||||
|
||||
use rand::prelude::*;
|
||||
|
||||
use account::{Account};
|
||||
use account;
|
||||
use events::{Event};
|
||||
@ -132,11 +134,10 @@ pub trait User {
|
||||
}
|
||||
|
||||
struct Connection {
|
||||
pub id: Uuid,
|
||||
pub id: usize,
|
||||
pub ws: CbSender<RpcMessage>,
|
||||
pool: PgPool,
|
||||
stripe: StripeClient,
|
||||
// account: Option<Account>,
|
||||
user: Box<dyn User>,
|
||||
events: CbSender<Event>,
|
||||
}
|
||||
@ -199,8 +200,7 @@ impl Handler for Connection {
|
||||
let db = self.pool.get().unwrap();
|
||||
match account::from_token(&db, &cookie.value().to_string()) {
|
||||
Ok(a) => {
|
||||
self.id = a.id;
|
||||
self.user = Box::new(Authenticated::new(a, self.ws.clone(), self.events.clone(), self.pool.clone()));
|
||||
self.user = Box::new(Authenticated::new(self.id, a, self.ws.clone(), self.events.clone(), self.pool.clone()));
|
||||
},
|
||||
Err(_) => return unauth(),
|
||||
}
|
||||
@ -243,12 +243,12 @@ pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
||||
}
|
||||
});
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let anon_account = Account::anonymous();
|
||||
let id = anon_account.id;
|
||||
|
||||
DeflateHandler::new(
|
||||
Connection {
|
||||
id,
|
||||
id: rng.gen::<usize>(),
|
||||
ws: tx.clone(),
|
||||
pool: pool.clone(),
|
||||
stripe: stripe.clone(),
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use mnml_core::mob::anim_test_game;
|
||||
use mnml_core::item::item_info;
|
||||
use std::time::Instant;
|
||||
use uuid::Uuid;
|
||||
|
||||
use failure::Error;
|
||||
use failure::err_msg;
|
||||
@ -44,7 +43,7 @@ use rpc::{RpcMessage, RpcRequest, User};
|
||||
#[derive(Debug,Clone)]
|
||||
pub struct Authenticated {
|
||||
pub account: Account,
|
||||
pub id: Uuid,
|
||||
pub id: usize,
|
||||
|
||||
events: CbSender<Event>,
|
||||
ws: CbSender<RpcMessage>,
|
||||
@ -52,9 +51,9 @@ pub struct Authenticated {
|
||||
}
|
||||
|
||||
impl Authenticated {
|
||||
pub fn new(account: Account, ws: CbSender<RpcMessage>, events: CbSender<Event>, pool: PgPool) -> Authenticated {
|
||||
pub fn new(id: usize, account: Account, ws: CbSender<RpcMessage>, events: CbSender<Event>, pool: PgPool) -> Authenticated {
|
||||
Authenticated {
|
||||
id: account.id,
|
||||
id,
|
||||
account,
|
||||
ws,
|
||||
events,
|
||||
@ -81,10 +80,10 @@ impl User for Authenticated {
|
||||
|
||||
// last minute processing
|
||||
let msg = match msg {
|
||||
RpcMessage::InstanceState(v) => RpcMessage::InstanceState(v.redact(self.id)),
|
||||
RpcMessage::InstanceState(v) => RpcMessage::InstanceState(v.redact(self.account.id)),
|
||||
RpcMessage::AccountInstances(v) =>
|
||||
RpcMessage::AccountInstances(v.into_iter().map(|i| i.redact(self.id)).collect()),
|
||||
RpcMessage::GameState(v) => RpcMessage::GameState(v.redact(self.id)),
|
||||
RpcMessage::AccountInstances(v.into_iter().map(|i| i.redact(self.account.id)).collect()),
|
||||
RpcMessage::GameState(v) => RpcMessage::GameState(v.redact(self.account.id)),
|
||||
_ => msg,
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-studios",
|
||||
"version": "1.12.4",
|
||||
"version": "1.13.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user