Merge branch 'develop' into menu-tabs

This commit is contained in:
ntr 2019-09-04 20:16:37 +10:00
commit db377ff7b2
15 changed files with 398 additions and 56 deletions

View File

@ -1 +1 @@
1.1.0
1.2.0

View File

@ -1,6 +1,6 @@
{
"name": "mnml-client",
"version": "1.1.0",
"version": "1.2.0",
"description": "",
"main": "index.js",
"scripts": {

View File

@ -60,6 +60,22 @@
height: 1em;
}
.instance .info figure {
display: inline;
height: 0.5em;
svg {
margin-right: 0.5em;
}
}
.instance .info figcaption {
font-size: 1em;
display: inline-block;
vertical-align: middle;
}
.instance .constructs {
grid-area: constructs;
}

View File

@ -1,6 +1,6 @@
{
"name": "mnml-client",
"version": "1.1.0",
"version": "1.2.0",
"description": "",
"main": "index.js",
"scripts": {

View File

@ -28,11 +28,16 @@ function InfoComponent(args) {
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
const itemSource = itemInfo.combos.filter(c => c.item === info);
const itemSourceInfo = itemSource.length
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
: false;
const itemRegEx = /(Red|Blue|Green)/;
const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
return (
<div class="info-skill">
<h2>{fullInfo.item}</h2>
<h3>Skill > BB</h3>
<h3>tri 3</h3>
<h3>{itemSourceDescription}</h3>
<div> {infoDescription} </div>
</div>
);

View File

@ -100,9 +100,79 @@ module.exports = {
{square(['red', 'blue'])}
<figcaption>Life</figcaption>
</figure>,
LifeGGPlus: () =>
<figure>
{square(['green'])}
<figcaption>Life+</figcaption>
</figure>,
LifeRRPlus: () =>
<figure>
{square(['red'])}
<figcaption>Life+</figcaption>
</figure>,
// Power Upgrades
LifeBBPlus:() =>
<figure>
{square(['blue'])}
<figcaption>Life+</figcaption>
</figure>,
LifeRGPlus: () =>
<figure>
{square(['red', 'green'])}
<figcaption>Life+</figcaption>
</figure>,
LifeGBPlus: () =>
<figure>
{square(['green', 'blue'])}
<figcaption>Life+</figcaption>
</figure>,
LifeRBPlus:() =>
<figure>
{square(['red', 'blue'])}
<figcaption>Life+</figcaption>
</figure>,
LifeGGPlusPlus: () =>
<figure>
{square(['green'])}
<figcaption>Life++</figcaption>
</figure>,
LifeRRPlusPlus: () =>
<figure>
{square(['red'])}
<figcaption>Life++</figcaption>
</figure>,
LifeBBPlusPlus:() =>
<figure>
{square(['blue'])}
<figcaption>Life++</figcaption>
</figure>,
LifeRGPlusPlus: () =>
<figure>
{square(['red', 'green'])}
<figcaption>Life++</figcaption>
</figure>,
LifeGBPlusPlus: () =>
<figure>
{square(['green', 'blue'])}
<figcaption>Life++</figcaption>
</figure>,
LifeRBPlusPlus:() =>
<figure>
{square(['red', 'blue'])}
<figcaption>Life++</figcaption>
</figure>,
// Powers Upgrades
PowerGG: () =>
<figure>
{circle(['green'])}
@ -138,8 +208,79 @@ module.exports = {
{circle(['red', 'blue'])}
<figcaption>Power</figcaption>
</figure>,
PowerGGPlus: () =>
<figure>
{circle(['green'])}
<figcaption>Power+</figcaption>
</figure>,
// Speed Upgrades
PowerRRPlus: () =>
<figure>
{circle(['red'])}
<figcaption>Power+</figcaption>
</figure>,
PowerBBPlus:() =>
<figure>
{circle(['blue'])}
<figcaption>Power+</figcaption>
</figure>,
PowerRGPlus: () =>
<figure>
{circle(['red', 'green'])}
<figcaption>Power+</figcaption>
</figure>,
PowerGBPlus: () =>
<figure>
{circle(['green', 'blue'])}
<figcaption>Power+</figcaption>
</figure>,
PowerRBPlus:() =>
<figure>
{circle(['red', 'blue'])}
<figcaption>Power+</figcaption>
</figure>,
PowerGGPlusPlus: () =>
<figure>
{circle(['green'])}
<figcaption>Power++</figcaption>
</figure>,
PowerRRPlusPlus: () =>
<figure>
{circle(['red'])}
<figcaption>Power++</figcaption>
</figure>,
PowerBBPlusPlus:() =>
<figure>
{circle(['blue'])}
<figcaption>Power++</figcaption>
</figure>,
PowerRGPlusPlus: () =>
<figure>
{circle(['red', 'green'])}
<figcaption>Power++</figcaption>
</figure>,
PowerGBPlusPlus: () =>
<figure>
{circle(['green', 'blue'])}
<figcaption>Power++</figcaption>
</figure>,
PowerRBPlusPlus:() =>
<figure>
{circle(['red', 'blue'])}
<figcaption>Power++</figcaption>
</figure>,
// Speeds Upgrades
SpeedGG: () =>
<figure>
{triangle(['green'])}
@ -175,4 +316,75 @@ module.exports = {
{triangle(['red', 'blue'])}
<figcaption>Speed</figcaption>
</figure>,
SpeedGGPlus: () =>
<figure>
{triangle(['green'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedRRPlus: () =>
<figure>
{triangle(['red'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedBBPlus:() =>
<figure>
{triangle(['blue'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedRGPlus: () =>
<figure>
{triangle(['red', 'green'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedGBPlus: () =>
<figure>
{triangle(['green', 'blue'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedRBPlus:() =>
<figure>
{triangle(['red', 'blue'])}
<figcaption>Speed+</figcaption>
</figure>,
SpeedGGPlusPlus: () =>
<figure>
{triangle(['green'])}
<figcaption>Speed++</figcaption>
</figure>,
SpeedRRPlusPlus: () =>
<figure>
{triangle(['red'])}
<figcaption>Speed++</figcaption>
</figure>,
SpeedBBPlusPlus:() =>
<figure>
{triangle(['blue'])}
<figcaption>Speed++</figcaption>
</figure>,
SpeedRGPlusPlus: () =>
<figure>
{triangle(['red', 'green'])}
<figcaption>Speed++</figcaption>
</figure>,
SpeedGBPlusPlus: () =>
<figure>
{triangle(['green', 'blue'])}
<figcaption>Speed++</figcaption>
</figure>,
SpeedRBPlusPlus:() =>
<figure>
{triangle(['red', 'blue'])}
<figcaption>Speed++</figcaption>
</figure>,
};

View File

@ -305,7 +305,6 @@ function Vbox(args) {
const highlighted = combiner.indexOf(i) > -1;
const classes = `${highlighted ? 'highlight' : ''}`;
if (shapes[v]) {
return (
<button

View File

@ -228,6 +228,7 @@ function convertItem(v) {
shapes.vboxColour(v.toLowerCase())
);
}
if (shapes[v]) return shapes[v]();
return v || <span>&nbsp;</span>;
// uncomment for double borders in vbox;
// if (v) {

View File

@ -1,6 +1,6 @@
{
"name": "mnml-ops",
"version": "1.1.0",
"version": "1.2.0",
"description": "",
"main": "index.js",
"scripts": {

View File

@ -1,6 +1,6 @@
[package]
name = "mnml"
version = "1.1.0"
version = "1.2.0"
authors = ["ntr <ntr@smokestack.io>"]
[dependencies]

View File

@ -4,6 +4,7 @@ use std::collections::{HashMap, HashSet};
use uuid::Uuid;
use failure::Error;
use failure::{err_msg, format_err};
use crossbeam_channel::{Sender, Receiver};
@ -28,7 +29,7 @@ type Id = usize;
pub struct PvpRequest {
pub id: Id,
pub tx: Sender<RpcMessage>,
pub account: Account,
pub account: Uuid,
}
pub struct Events {
@ -37,8 +38,6 @@ pub struct Events {
mail: Sender<Mail>,
warden: Sender<GameEvent>,
queue: Option<PvpRequest>,
clients: HashMap<Id, WsClient>,
}
@ -54,13 +53,15 @@ pub enum Event {
Push(Uuid, RpcMessage),
// client events
Queue(PvpRequest),
Queue(Id),
}
struct WsClient {
id: Id,
account: Option<Uuid>,
tx: Sender<RpcMessage>,
subs: HashSet<Uuid>,
pvp: bool,
}
impl Events {
@ -70,7 +71,6 @@ impl Events {
rx,
warden,
mail,
queue: None,
clients: HashMap::new(),
}
}
@ -88,7 +88,7 @@ impl Events {
},
Err(e) => {
return Err(format_err!("events error err={:?}", e));
warn!("events error err={:?}", e);
},
};
}
@ -110,7 +110,12 @@ impl Events {
Event::Connect(id, account, tx) => {
info!("connect id={:?} account={:?}", id, account);
let client = WsClient { id, tx, subs: HashSet::new() };
let account_id = match account {
Some(a) => Some(a.id),
None => None,
};
let client = WsClient { id, tx, account: account_id, subs: HashSet::new(), pvp: false };
self.clients.insert(id, client);
info!("clients={:?}", self.clients.len());
@ -181,30 +186,43 @@ impl Events {
Ok(())
},
Event::Queue(req) => {
info!("queue id={:?} account={:?}", req.id, req.account);
Event::Queue(id) => {
// check whether request is valid
{
let c = self.clients.get(&id)
.ok_or(format_err!("connection not found id={:?}", id))?;
self.queue = match self.queue {
Some(ref q_req) => {
info!("game queue pair found a={:?} b={:?}", req.account, q_req.account);
self.warden.send(GameEvent::Match((req, q_req.clone())))?;
None
},
None => {
info!("joined game queue id={:?} account={:?}", req.id, req.account);
match self.clients.get(&req.id) {
Some(ref c) => {
c.tx.send(RpcMessage::QueueJoined(()))?;
Some(req)
},
None => return Err(format_err!("missing client client={:?}", req.id)),
}
},
};
if let None = c.account {
return Err(err_msg("cannot join pvp queue anonymously"));
}
Ok(())
info!("pvp queue request id={:?} account={:?}", c.id, c.account);
}
// create the req for the already queued opponent
if let Some(opp_req) = match self.clients.iter_mut().find(|(_c_id, c)| c.pvp) {
Some((q_id, q)) => {
q.pvp = false;
Some(PvpRequest { id: *q_id, account: q.account.unwrap(), tx: q.tx.clone() })
},
None => None,
} {
// combine the requests and send to warden
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.account.unwrap(), tx: c.tx.clone() };
self.warden.send(GameEvent::Match((opp_req, player_req)))?;
return Ok(())
}
// or flag the requester as pvp ready
let requester = self.clients.get_mut(&id).unwrap();
requester.pvp = true;
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
return Ok(());
},
}
}
}

View File

@ -76,7 +76,7 @@ impl TimeControl {
pub fn lobby_timeout(&self) -> DateTime<Utc> {
Utc::now()
.checked_add_signed(Duration::minutes(5))
.checked_add_signed(Duration::seconds(30))
.expect("could not set phase end")
}
@ -366,7 +366,7 @@ impl Instance {
}
fn current_game_id(&self) -> Option<Uuid> {
if self.phase == InstancePhase::Lobby {
if self.phase != InstancePhase::InProgress {
return None;
}
@ -691,9 +691,6 @@ pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result<Inst
Ok(instance)
}
// pub fn instance_queue(tx: &mut Transaction, a: &Account, b: &Account) -> Result<Instance, Error> {
// }
pub fn pvp(tx: &mut Transaction, a: &Account, b: &Account) -> Result<Instance, Error> {
let mut instance = Instance::new()
// TODO generate nice game names

View File

@ -44,139 +44,229 @@ pub enum Item {
LifeRBPlusPlus,
// Power Upgrades
PowerGG,
PowerRR,
PowerBB,
PowerGG,
PowerRG,
PowerGB,
PowerRB,
PowerRRPlus,
PowerGGPlus,
PowerRRPlus,
PowerBBPlus,
PowerRGPlus,
PowerGBPlus,
PowerRBPlus,
PowerGGPlusPlus,
PowerRRPlusPlus,
PowerBBPlusPlus,
PowerGGPlusPlus,
PowerRGPlusPlus,
PowerGBPlusPlus,
PowerRBPlusPlus,
// Speed Upgrades
SpeedGG,
SpeedRR,
SpeedBB,
SpeedGG,
SpeedRG,
SpeedGB,
SpeedRB,
SpeedGGPlus,
SpeedRRPlus,
SpeedBBPlus,
SpeedGGPlus,
SpeedRGPlus,
SpeedGBPlus,
SpeedRBPlus,
SpeedGGPlusPlus,
SpeedRRPlusPlus,
SpeedBBPlusPlus,
SpeedGGPlusPlus,
SpeedRGPlusPlus,
SpeedGBPlusPlus,
SpeedRBPlusPlus,
Amplify,
#[serde(rename = "Amplify+")]
AmplifyPlus,
#[serde(rename = "Amplify++")]
AmplifyPlusPlus,
Absorb,
#[serde(rename = "Absorb+")]
AbsorbPlus,
#[serde(rename = "Absorb++")]
AbsorbPlusPlus,
Banish,
#[serde(rename = "Banish+")]
BanishPlus,
#[serde(rename = "Banish++")]
BanishPlusPlus,
Bash,
#[serde(rename = "Bash+")]
BashPlus,
#[serde(rename = "Bash++")]
BashPlusPlus,
Blast,
#[serde(rename = "Blast+")]
BlastPlus,
#[serde(rename = "Blast++")]
BlastPlusPlus,
Chaos,
#[serde(rename = "Chaos+")]
ChaosPlus,
#[serde(rename = "Chaos++")]
ChaosPlusPlus,
Sustain,
#[serde(rename = "Sustain+")]
SustainPlus,
#[serde(rename = "Sustain++")]
SustainPlusPlus,
Electrify,
#[serde(rename = "Electrify+")]
ElectrifyPlus,
#[serde(rename = "Electrify++")]
ElectrifyPlusPlus,
Curse,
#[serde(rename = "Curse+")]
CursePlus,
#[serde(rename = "Curse++")]
CursePlusPlus,
Decay,
#[serde(rename = "Decay+")]
DecayPlus,
#[serde(rename = "Decay++")]
DecayPlusPlus,
Hex,
#[serde(rename = "Hex+")]
HexPlus,
#[serde(rename = "Hex++")]
HexPlusPlus,
Haste,
#[serde(rename = "Haste+")]
HastePlus,
#[serde(rename = "Haste++")]
HastePlusPlus,
Heal,
#[serde(rename = "Heal+")]
HealPlus,
#[serde(rename = "Heal++")]
HealPlusPlus,
Hybrid,
#[serde(rename = "Hybrid+")]
HybridPlus,
#[serde(rename = "Hybrid++")]
HybridPlusPlus,
Invert,
#[serde(rename = "Invert+")]
InvertPlus,
#[serde(rename = "Invert++")]
InvertPlusPlus,
Counter,
#[serde(rename = "Counter+")]
CounterPlus,
#[serde(rename = "Counter++")]
CounterPlusPlus,
Purge,
#[serde(rename = "Purge+")]
PurgePlus,
#[serde(rename = "Purge++")]
PurgePlusPlus,
Purify,
#[serde(rename = "Purify+")]
PurifyPlus,
#[serde(rename = "Purify++")]
PurifyPlusPlus,
Reflect,
#[serde(rename = "Reflect+")]
ReflectPlus,
#[serde(rename = "Reflect++")]
ReflectPlusPlus,
Recharge,
#[serde(rename = "Recharge+")]
RechargePlus,
#[serde(rename = "Recharge++")]
RechargePlusPlus,
Ruin,
#[serde(rename = "Ruin+")]
RuinPlus,
#[serde(rename = "Ruin++")]
RuinPlusPlus,
Link,
#[serde(rename = "Link+")]
LinkPlus,
#[serde(rename = "Link++")]
LinkPlusPlus,
Silence,
#[serde(rename = "Silence+")]
SilencePlus,
#[serde(rename = "Silence++")]
SilencePlusPlus,
Slay,
#[serde(rename = "Slay+")]
SlayPlus,
#[serde(rename = "Slay++")]
SlayPlusPlus,
Sleep,
#[serde(rename = "Sleep+")]
SleepPlus,
#[serde(rename = "Sleep++")]
SleepPlusPlus,
Restrict,
#[serde(rename = "Restrict+")]
RestrictPlus,
#[serde(rename = "Restrict++")]
RestrictPlusPlus,
Strike,
#[serde(rename = "Strike+")]
StrikePlus,
#[serde(rename = "Strike++")]
StrikePlusPlus,
Siphon,
#[serde(rename = "Siphon+")]
SiphonPlus,
#[serde(rename = "Siphon++")]
SiphonPlusPlus,
Intercept,
#[serde(rename = "Intercept+")]
InterceptPlus,
#[serde(rename = "Intercept++")]
InterceptPlusPlus,
Break,
#[serde(rename = "Break+")]
BreakPlus,
#[serde(rename = "Break++")]
BreakPlusPlus,
Triage,
#[serde(rename = "Triage+")]
TriagePlus,
#[serde(rename = "Triage++")]
TriagePlusPlus,
}

View File

@ -19,7 +19,7 @@ use ws::{listen, CloseCode, Message, Handler, Request, Response};
use account::{Account};
use account;
use construct::{Construct};
use events::{Event, PvpRequest};
use events::{Event};
use game::{Game, game_state, game_skill, game_ready};
use instance::{Instance, instance_state, instance_practice, instance_ready};
use item::{Item, ItemInfoCtr, item_info};
@ -132,8 +132,7 @@ impl Connection {
// evented but authorization required
match v {
RpcRequest::InstanceQueue {} => {
let pvp = PvpRequest { id: self.id, account: account.clone(), tx: self.ws.clone() };
self.events.send(Event::Queue(pvp))?;
self.events.send(Event::Queue(self.id))?;
return Ok(RpcMessage::QueueRequested(()));
},
_ => (),

View File

@ -8,6 +8,7 @@ use crossbeam_channel::{tick, Sender, Receiver};
use postgres::transaction::Transaction;
use failure::Error;
use account;
use game::{games_need_upkeep, game_update, game_write, game_delete};
use instance;
use instance::{instances_need_upkeep, instances_idle, instance_update, instance_delete};
@ -57,7 +58,7 @@ impl Warden {
},
Err(e) => {
return Err(format_err!("err={:?}", e));
warn!("err={:?}", e);
},
};
}
@ -91,7 +92,11 @@ impl Warden {
let db = self.pool.get()?;
let mut tx = db.transaction()?;
let instance = instance::pvp(&mut tx, &pair.0.account, &pair.1.account)?;
let a = account::select(&db, pair.0.account)?;
let b = account::select(&db, pair.1.account)?;
let instance = instance::pvp(&mut tx, &a, &b)?;
tx.commit()?;
// subscribe users to instance events