Merge branch 'develop' of ssh://git.mnml.gg:40022/~/mnml into develop

This commit is contained in:
Mashy 2019-09-12 12:10:01 +10:00
commit 2086badbdf
60 changed files with 442 additions and 160 deletions

View File

@ -19,7 +19,6 @@
* msg pane * msg pane
* game invites * game invites
* change score to enum
* add speed to descriptions * add speed to descriptions

View File

@ -77,6 +77,12 @@
} }
} }
} }
.login {
display: flex;
flex-flow: column;
margin-bottom: 2em;
}
} }
section { section {
@ -108,4 +114,60 @@ section {
display: flex; display: flex;
flex-flow: column; flex-flow: column;
} }
}
.demo {
margin-top: 1em;
display: grid;
grid-template-areas:
"vinfo game"
"vcons game";
grid-template-columns: 1fr 1fr;
grid-template-rows: min-content 1fr;
.colour-info {
grid-area: vinfo;
display: flex;
align-items: center;
div {
display: flex;
}
svg {
flex: 1;
height: 1em;
}
}
.vbox-demo {
grid-area: vinfo;
}
.game-demo {
grid-area: game;
display: grid;
grid-template-columns: 1fr 2fr;
.game {
display: flex;
flex-flow: column;
.game-construct {
flex: 1;
}
}
}
.construct-list {
grid-area: vcons;
height: 100%;
svg {
height: 100%;
}
}
} }

View File

@ -195,28 +195,6 @@ button[disabled] {
border-color: #222; border-color: #222;
} }
/*
LOGIN
*/
.welcome {
.login {
width: 50%;
display: flex;
flex-flow: column;
margin-bottom: 2em;
}
.options {
display: flex;
width: 50%;
}
h2 {
margin-bottom: 0.5em;
}
}
#mnml input, #mnml select { #mnml input, #mnml select {
border-color: #222; border-color: #222;
background-color: #222; background-color: #222;
@ -272,14 +250,6 @@ header {
color: @white; color: @white;
box-shadow: inset 0px 5px 0px 0px @white; box-shadow: inset 0px 5px 0px 0px @white;
border: 0; border: 0;
&:first-child {
border-left: 1px solid #444;
}
&:last-child {
border-right: 1px solid #444;
}
} }
border: 1px solid #444; border: 1px solid #444;

View File

@ -8,6 +8,8 @@ export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value });
export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value }); export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value });
export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value }); export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value });
export const setDemo = value => ({ type: 'SET_DEMO', value });
export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null });
export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });

View File

@ -68,6 +68,7 @@ class ConstructAnimation extends Component {
const animSkill = removeTier(skill); const animSkill = removeTier(skill);
if (!constructId.includes(construct.id)) return false; if (!constructId.includes(construct.id)) return false;
// find target animation // find target animation
const chooseAnim = (animSkill) => { const chooseAnim = (animSkill) => {
switch (animSkill) { switch (animSkill) {

View File

@ -90,7 +90,7 @@ class Absorb extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -78,7 +78,7 @@ class Amplify extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -59,7 +59,7 @@ class Attack extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -100,7 +100,7 @@ class Bash extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -103,7 +103,7 @@ class Bash extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -88,7 +88,7 @@ class Blast extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -53,7 +53,7 @@ class Block extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -107,7 +107,7 @@ class Break extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -81,7 +81,7 @@ class Buff extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -119,7 +119,7 @@ class Chaos extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -85,7 +85,7 @@ class Counter extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -78,7 +78,7 @@ class Curse extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -83,7 +83,7 @@ class Debuff extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -68,7 +68,7 @@ class Decay extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -109,7 +109,7 @@ class Electrify extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -101,7 +101,7 @@ class Electrocute extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -83,7 +83,7 @@ class Haste extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -81,7 +81,7 @@ class Heal extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -88,7 +88,7 @@ class Hex extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -153,7 +153,7 @@ class Hybrid extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -96,7 +96,7 @@ class Intercept extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -91,7 +91,7 @@ class Link extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -81,7 +81,7 @@ class Purge extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -115,7 +115,7 @@ class Purify extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -95,7 +95,7 @@ class Recharge extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -76,7 +76,7 @@ class Block extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -82,7 +82,7 @@ class Intercept extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -77,7 +77,7 @@ class Refl extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -102,7 +102,7 @@ class Restrict extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -100,7 +100,7 @@ class Ruin extends Component {
this.animations[i].reset(); this.animations[i].reset();
} }
try { try {
this.props.animCb(); this.props.animCb && this.props.animCb();
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }

View File

@ -97,7 +97,7 @@ class Silence extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -69,7 +69,7 @@ class Siphon extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -116,7 +116,7 @@ class SiphonTick extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -152,7 +152,7 @@ class Slay extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -140,7 +140,7 @@ class Sleep extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -120,7 +120,7 @@ class Strike extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -78,7 +78,7 @@ class Stun extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -127,7 +127,7 @@ class Sustain extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -80,7 +80,7 @@ class Triage extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -79,7 +79,7 @@ class TriageTick extends Component {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} }
this.props.animCb(); this.props.animCb && this.props.animCb();
} }
} }

View File

@ -0,0 +1,177 @@
const { connect } = require('preact-redux');
const preact = require('preact');
const actions = require('../actions');
const shapes = require('./shapes');
const { ConstructAvatar } = require('./construct');
const { ConstructAnimation } = require('./animations');
const addState = connect(
function receiveState(state) {
const {
account,
itemInfo,
demo,
} = state;
return {
account,
itemInfo,
demo,
};
},
function receiveDispatch(dispatch) {
function setAnimTarget(anim) {
dispatch(actions.setAnimTarget(anim));
}
return { setAnimTarget };
}
);
function Demo(args) {
const {
demo,
itemInfo,
account,
setAnimTarget,
} = args;
if (!demo || !itemInfo.items.length || account) return false;
const { combiner, items, equipping, equipped, players } = demo;
console.log(items);
const vboxDemo = () => {
function inventoryBtn(i, j) {
if (!i) return <button disabled class='empty' >&nbsp;</button>;
const highlighted = combiner.indexOf(j) > -1;
const classes = `${highlighted ? 'highlight' : ''}`;
if (shapes[i]) {
return <button class={classes} key={j}>{shapes[i]()}</button>;
}
return <button class={classes}>{i}</button>;
}
function combinerBtn() {
let text = '';
if (combiner.length < 3) {
for (let i = 0; i < 3; i++) {
if (combiner.length > i) {
text += '■ ';
} else {
text += '▫ ';
}
}
} else {
text = 'combine';
}
return (
<button
class='vbox-btn'
disabled={combiner.length !== 3}>
{text}
</button>
);
}
function inventoryElement() {
return (
<div class="vbox">
<div class='vbox-section'>
<h2 class='colour-info'>
VBOX PHASE {shapes.Red()} {shapes.Green()} {shapes.Blue()}
</h2>
<p>
combine the colour base items with an array of skills and specialisations to build powerful variants.
</p>
</div>
<div>&nbsp;</div>
<div class='vbox-section'>
<div class='vbox-items'>
{items.map((i, j) => inventoryBtn(i, j))}
</div>
{combinerBtn()}
</div>
</div>
);
}
return (
<div class="news vbox-demo">
{inventoryElement()}
</div>
);
};
const vboxConstructs = () => {
const btnClass = equipping
? 'equipping empty gray'
: 'empty gray';
return (
<div class='news construct-list'>
{players[0].constructs.map((c, i) => (
<div class="instance-construct" key={i}>
<h2 class="name" >{c.name}</h2>
<ConstructAvatar construct={c} />
<div class="skills">
{i === 0 && equipped
? <button>Strike</button>
: <button disabled={!equipping} class={btnClass}>SKILL</button>
}
<button disabled={!equipping} class={btnClass}>SKILL</button>
<button disabled={!equipping} class={btnClass}>SKILL</button>
</div>
<div class="specs">
</div>
<div class="stats">
</div>
</div>
))}
</div>
);
};
const gameDemo = () => {
return (
<div class="game-demo">
<div>
<h2>GAME PHASE</h2>
<p>Outplay noobs wahtever write tomorrow, fix the tiemout shit.</p>
<p>also have to just picka random avatar so i don't fill up my drive</p>
</div>
<div class="game">
<div class="game-construct">
<ConstructAvatar construct={players[1].constructs[0]} />
<ConstructAnimation construct={players[1].constructs[0]} />
</div>
<div></div>
<div class="game-construct">
<ConstructAvatar construct={players[1].constructs[1]} />
<ConstructAnimation construct={players[1].constructs[1]} />
</div>
</div>
</div>
);
};
return (
<section class='demo news'>
{vboxDemo()}
{vboxConstructs()}
{gameDemo()}
</section>
);
}
module.exports = addState(Demo);

View File

@ -42,7 +42,6 @@ const addState = connect(
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {
function setActiveSkill(constructId, skill) { function setActiveSkill(constructId, skill) {
dispatch(actions.setActiveSkill(constructId, skill)); dispatch(actions.setActiveSkill(constructId, skill));
// particlesJS(`particles-${constructId}`, config);
} }
function setActiveConstruct(construct) { function setActiveConstruct(construct) {

View File

@ -21,15 +21,14 @@ function InfoComponent(args) {
return ( return (
<div> <div>
<h2>VBOX phase</h2> <h2>VBOX phase</h2>
<p>in this phase you strengthen and specialise your constructs by equipping items to them.</p> <p>strengthen and specialise your constructs by equipping items to them.</p>
<p>double clicking items in the <b>VBOX</b> will purchase and move them to your <b>INVENTORY</b>.</p> <p>double click to purchase items in the <b>VBOX</b> and move them to your <b>INVENTORY</b>.</p>
<p> <p>
hover over an item to see its effects and combinations.<br />
combine a <b>SKILL</b> or <b>SPEC</b> with 2 <b>COLOURS</b> to create an item.<br /> combine a <b>SKILL</b> or <b>SPEC</b> with 2 <b>COLOURS</b> to create an item.<br />
combine 3 of the same item to upgrade it.<br /> combine <b>3 of the same item</b> to upgrade it.<br />
click an item and then click a construct to equip that item to it.<br /> click an item and then click a construct to <b>equip</b> that item to it.<br />
</p> </p>
<p>click the <b>READY</b> button on the right to progress to the <b>GAME PHASE</b>.</p> <p>click the <b>READY</b> button for the <b>GAME PHASE</b>.</p>
</div> </div>
); );
} }

View File

@ -1,18 +1,11 @@
const preact = require('preact'); const preact = require('preact');
module.exports = function molecule(combatText) { module.exports = function molecule() {
const text = combatText return (
? <text x="0" y="400" class="combat-text"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 500">
{combatText} <rect style="fill: none;"></rect>
<animate attributeType="XML" attributeName="y" from="300" to="200" dur="2s" repeatCount="1"/> <g transform="translate(-133.97462520598594, -116.025374794014) "><g><line x1="325.9602631261639" x2="296.95475676906796" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="267.949250411972" x2="296.95475676906796" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="383.9712758403558" y1="433.01268739700697" y2="466.5063436985035" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="383.9712758403558" x2="383.9712758403558" y1="500" y2="466.5063436985035" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="383.9712758403558" y1="299.038062191021" y2="265.5444058895245" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="383.9712758403558" x2="383.9712758403558" y1="232.050749588028" y2="265.5444058895245" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="500" x2="470.994493642904" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke: #1FF01F; stroke-width: 3; stroke-linecap: butt;"></line><line x1="441.98898728580804" x2="470.994493642904" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="470.994493642904" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="500" x2="470.994493642904" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="325.9602631261639" x2="296.95475676906796" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="267.949250411972" x2="296.95475676906796" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="354.96576948325986" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="325.9602631261639" x2="354.96576948325986" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="412.98013156308195" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="383.9712758403558" x2="412.98013156308195" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="325.9602631261639" x2="325.9602631261639" y1="332.53171849251754" y2="366.02537479401406" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="325.9602631261639" x2="325.9602631261639" y1="399.5190310955105" y2="366.02537479401406" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="383.9712758403558" x2="412.98013156308195" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="441.98898728580804" x2="412.98013156308195" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="325.9602631261639" x2="354.96576948325986" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="383.9712758403558" x2="354.96576948325986" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="441.98898728580804" y1="399.5190310955105" y2="366.02537479401406" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="441.98898728580804" x2="441.98898728580804" y1="332.53171849251754" y2="366.02537479401406" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g class="atom" transform="translate(267.949250411972, 299.038062191021) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(383.9712758403558, 500) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(383.9712758403558, 232.050749588028) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(500, 433.01268739700697) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(500, 299.038062191021) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(267.949250411972, 433.01268739700697) "><circle r="8" style="fill: #1FF01F;"></circle></g>
<animate attributeType="XML" attributeName="opacity" from="1" to="0" dur="2s" repeatCount="1"/> </g>
</text> </svg>
: ''; );
return (<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 500">
<rect style="fill: none;"></rect>
<g transform="translate(-133.97462520598594, -116.025374794014) "><g><line x1="325.9602631261639" x2="296.95475676906796" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="267.949250411972" x2="296.95475676906796" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="383.9712758403558" y1="433.01268739700697" y2="466.5063436985035" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="383.9712758403558" x2="383.9712758403558" y1="500" y2="466.5063436985035" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="383.9712758403558" y1="299.038062191021" y2="265.5444058895245" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="383.9712758403558" x2="383.9712758403558" y1="232.050749588028" y2="265.5444058895245" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="500" x2="470.994493642904" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke: #1FF01F; stroke-width: 3; stroke-linecap: butt;"></line><line x1="441.98898728580804" x2="470.994493642904" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="470.994493642904" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="500" x2="470.994493642904" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="325.9602631261639" x2="296.95475676906796" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: butt;"></line><line x1="267.949250411972" x2="296.95475676906796" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #1FF01F;"></line></g><g><line x1="383.9712758403558" x2="354.96576948325986" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="325.9602631261639" x2="354.96576948325986" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="412.98013156308195" y1="332.53171849251754" y2="315.78489034176926" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="383.9712758403558" x2="412.98013156308195" y1="299.038062191021" y2="315.78489034176926" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="325.9602631261639" x2="325.9602631261639" y1="332.53171849251754" y2="366.02537479401406" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="325.9602631261639" x2="325.9602631261639" y1="399.5190310955105" y2="366.02537479401406" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="383.9712758403558" x2="412.98013156308195" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="441.98898728580804" x2="412.98013156308195" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="325.9602631261639" x2="354.96576948325986" y1="399.5190310955105" y2="416.26585924625874" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="383.9712758403558" x2="354.96576948325986" y1="433.01268739700697" y2="416.26585924625874" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g><line x1="441.98898728580804" x2="441.98898728580804" y1="399.5190310955105" y2="366.02537479401406" transform="" style="stroke: #909090; stroke-width: 3; stroke-linecap: round;"></line><line x1="441.98898728580804" x2="441.98898728580804" y1="332.53171849251754" y2="366.02537479401406" transform="" style="stroke-width: 3; stroke: #909090;"></line></g><g class="atom" transform="translate(267.949250411972, 299.038062191021) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(383.9712758403558, 500) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(383.9712758403558, 232.050749588028) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(500, 433.01268739700697) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(500, 299.038062191021) "><circle r="8" style="fill: #1FF01F;"></circle></g><g class="atom" transform="translate(267.949250411972, 433.01268739700697) "><circle r="8" style="fill: #1FF01F;"></circle></g>
</g>
{text}
</svg>);
}; };

View File

@ -5,6 +5,7 @@ const Login = require('./welcome.login');
const Register = require('./welcome.register'); const Register = require('./welcome.register');
const Help = require('./welcome.help'); const Help = require('./welcome.help');
const About = require('./welcome.about'); const About = require('./welcome.about');
const Demo = require('./demo');
function Welcome() { function Welcome() {
const page = this.state.page || 'login'; const page = this.state.page || 'login';
@ -19,41 +20,57 @@ function Welcome() {
}; };
return ( return (
<main class="welcome"> <main class="menu">
<h1>mnml.gg</h1> <header>
<div class="login"> <div class="options">
<div>mnml is an abstract turn based strategy game</div> <button
<div>free to play</div> class={`login-btn ${page === 'login' ? 'highlight' : ''}`}
<div>no email required</div> disabled={page === 'login'}
<div>glhf</div> onClick={() => this.setState({ page: 'login' })}>
Login
</button>
<button
class={`login-btn ${page === 'register' ? 'highlight' : ''}`}
disabled={page === 'register'}
onClick={() => this.setState({ page: 'register' })}>
Register
</button>
<button
class={`login-btn ${page === 'about' ? 'highlight' : ''}`}
disabled={page === 'about'}
onClick={() => this.setState({ page: 'about' })}>
About
</button>
<button
class={`login-btn ${page === 'help' ? 'highlight' : ''}`}
disabled={page === 'help'}
onClick={() => this.setState({ page: 'help' })}>
Help
</button>
</div>
</header>
<div class="top">
<section>
<div class="news">
<h1>mnml.gg</h1>
<p>
mnml is a turn-based 1v1 strategy game in an abstract setting.<br />
outplay your opponents by building your team of 3 constructs from a shifting meta of skills, effects and specialisations.<br />
</p>
<p>
simple rules, complex interactions, simultaneous turns to increase the pace, and a unique speed mechanic;<br />
mnml is a tactical game unlike any other.
</p>
<p>
free to play<br />
no email required<br />
glhf
</p>
</div>
{pageEl()}
</section>
</div> </div>
<div class="options"> <Demo />
<button
class={`login-btn ${page === 'login' ? 'highlight' : ''}`}
disabled={page === 'login'}
onClick={() => this.setState({ page: 'login' })}>
Login
</button>
<button
class={`login-btn ${page === 'register' ? 'highlight' : ''}`}
disabled={page === 'register'}
onClick={() => this.setState({ page: 'register' })}>
Register
</button>
<button
class={`login-btn ${page === 'about' ? 'highlight' : ''}`}
disabled={page === 'about'}
onClick={() => this.setState({ page: 'about' })}>
About
</button>
<button
class={`login-btn ${page === 'help' ? 'highlight' : ''}`}
disabled={page === 'help'}
onClick={() => this.setState({ page: 'help' })}>
Help
</button>
</div>
{pageEl()}
</main> </main>
); );
} }

View File

@ -12,8 +12,8 @@ const addState = connect(
ws ws
} = state; } = state;
function submitRegister(name, password, code) { function submitRegister(name, password) {
postData('/account/register', { name, password, code }) postData('/account/register', { name, password })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
if (data.error) return errorToast(data.error); if (data.error) return errorToast(data.error);
@ -34,12 +34,11 @@ function Register(args) {
submitRegister, submitRegister,
} = args; } = args;
const { password, confirm, name, code } = this.state; const { password, confirm, name } = this.state;
const registerSubmit = (event) => { const registerSubmit = (event) => {
event.preventDefault(); event.preventDefault();
submitRegister(name, password, code); submitRegister(name, password);
// this.setState({ name: '', password: '', confirm: '', code: ''});
} }
const registerConfirm = () => const registerConfirm = () =>
@ -75,14 +74,6 @@ function Register(args) {
value={this.state.confirm} value={this.state.confirm}
onInput={linkState(this, 'confirm')} onInput={linkState(this, 'confirm')}
/> />
<label for="code">Access Code</label>
<input
class="login-input"
type="text"
placeholder="code"
value={this.state.code}
onInput={linkState(this, 'code')}
/>
<button <button
class="login-btn" class="login-btn"
disabled={registerDisabled()} disabled={registerDisabled()}

View File

@ -1,3 +1,5 @@
const preact = require('preact');
const SOURCE_DURATION_MS = 1000; const SOURCE_DURATION_MS = 1000;
const TARGET_DELAY_MS = 500; const TARGET_DELAY_MS = 500;
const TARGET_DURATION_MS = 1500; const TARGET_DURATION_MS = 1500;
@ -24,15 +26,11 @@ module.exports = {
INFO: { INFO: {
vbox: { vbox: {
item: 'VBOX', item: 'VBOX',
description: 'Contains ITEMS that are available for you to buy.\nDouble-click to purchase.', description: <p><b>ITEMS</b> that are available to buy.<br />the <b>VBOX</b> is refilled every round.<br />click <b>REFILL</b> at the bottom to purchase a refill. </p>,
}, },
inventory: { inventory: {
item: 'INVENTORY', item: 'INVENTORY',
description: 'Holds purchased ITEMS.\nClick to add ITEM to I-COMBINATOR.', description: <p>holds <b>ITEMS</b><br /><b>ITEMS</b> carry over each round.</p>,
},
combiner: {
item: 'I-COMBINATOR',
description: 'Combines purchased ITEMS into more powerful variants. Hover over an ITEM to see recipes.',
}, },
bits: { bits: {
item: 'BITS', item: 'BITS',
@ -51,12 +49,12 @@ module.exports = {
description: 'Reclaim ITEMS for half the purchase cost of their combined ITEMS.\nClick to enable and click ITEM to reclaim.', description: 'Reclaim ITEMS for half the purchase cost of their combined ITEMS.\nClick to enable and click ITEM to reclaim.',
}, },
refine: { refine: {
item: 'REFINE', item: 'COMBINE',
description: 'Refine ITEMS currently in I-COMBINATOR into more powerful variants', description: <p>combine the selected items.<br />hover over an item to see <b>RECIPES</b>.</p>,
}, },
refill: { refill: {
item: 'REFILL', item: 'REFILL',
description: 'Refill the VBOX with new ITEMS.', description: 'Refill the VBOX with new items.',
}, },
equipSkills: { equipSkills: {
item: 'QUICK ACCESS - SKILLS', item: 'QUICK ACCESS - SKILLS',

View File

@ -1,4 +1,5 @@
const eachSeries = require('async/eachSeries'); const eachSeries = require('async/eachSeries');
const sample = require('lodash/sample');
const actions = require('./actions'); const actions = require('./actions');
const { TIMES } = require('./constants'); const { TIMES } = require('./constants');
@ -187,6 +188,53 @@ function registerEvents(store) {
return store.dispatch(actions.setItemInfo(v)); return store.dispatch(actions.setItemInfo(v));
} }
function setDemo(d) {
const initial = {
players: d,
combiner: [],
items: ['Red', 'Red', 'Attack'],
equipped: false,
equipping: false,
};
const startDemo = () => {
console.log(initial);
store.dispatch(actions.setDemo(initial));
store.dispatch(actions.setAnimTarget(null));
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0] }))), 2000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1] }))), 4000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1, 2] }))), 6000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['Strike', '', ''] }))), 8000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0], items: ['Strike', '', ''], equipping: true }))), 10000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 12000);
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { items: ['', '', ''], equipped: true, equipping: false }))), 12000);
setTimeout(() => {
const { itemInfo } = store.getState();
return store.dispatch(actions.setAnimTarget({
skill: sample(itemInfo.items.filter(i => i.skill)).item,
constructId: d[1].constructs[0].id,
player: false,
direction: 0,
}));
}, 14000);
setTimeout(() => {
const { itemInfo } = store.getState();
return store.dispatch(actions.setAnimTarget({
skill: sample(itemInfo.items.filter(i => i.skill)).item,
constructId: d[1].constructs[1].id,
player: true,
direction: 0,
}));
}, 16000);
setTimeout(startDemo, 20000);
};
startDemo();
}
// events.on('SET_PLAYER', setInstance); // events.on('SET_PLAYER', setInstance);
// events.on('SEND_SKILL', function skillActive(gameId, constructId, targetConstructId, skill) { // events.on('SEND_SKILL', function skillActive(gameId, constructId, targetConstructId, skill) {
@ -230,6 +278,7 @@ function registerEvents(store) {
setAccountInstances, setAccountInstances,
setActiveItem, setActiveItem,
setActiveSkill, setActiveSkill,
setDemo,
setConstructList, setConstructList,
setNewConstruct, setNewConstruct,
setGame, setGame,

View File

@ -23,6 +23,8 @@ module.exports = {
animTarget: createReducer(null, 'SET_ANIM_TARGET'), animTarget: createReducer(null, 'SET_ANIM_TARGET'),
animText: createReducer(null, 'SET_ANIM_TEXT'), animText: createReducer(null, 'SET_ANIM_TEXT'),
demo: createReducer(null, 'SET_DEMO'),
combiner: createReducer([], 'SET_COMBINER'), combiner: createReducer([], 'SET_COMBINER'),
constructs: createReducer([], 'SET_CONSTRUCTS'), constructs: createReducer([], 'SET_CONSTRUCTS'),
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),

View File

@ -206,6 +206,10 @@ function createSocket(events) {
events.setItemInfo(info); events.setItemInfo(info);
} }
function onDemo(v) {
events.setDemo(v);
}
let pongTimeout; let pongTimeout;
function onPong() { function onPong() {
events.setPing(Date.now() - ping); events.setPing(Date.now() - ping);
@ -231,6 +235,7 @@ function createSocket(events) {
InstanceState: onInstanceState, InstanceState: onInstanceState,
ItemInfo: onItemInfo, ItemInfo: onItemInfo,
Pong: onPong, Pong: onPong,
Demo: onDemo,
QueueRequested: () => events.notify('pvp queue request received'), QueueRequested: () => events.notify('pvp queue request received'),
QueueJoined: () => events.notify('you have joined the pvp queue'), QueueJoined: () => events.notify('you have joined the pvp queue'),

View File

@ -288,15 +288,11 @@ pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Resul
Ok(name) Ok(name)
} }
pub fn create(name: &String, password: &String, code: &String, tx: &mut Transaction) -> Result<String, MnmlHttpError> { pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result<String, MnmlHttpError> {
if password.len() < PASSWORD_MIN_LEN { if password.len() < PASSWORD_MIN_LEN {
return Err(MnmlHttpError::PasswordUnacceptable); return Err(MnmlHttpError::PasswordUnacceptable);
} }
if code.to_lowercase() != "grep842" {
return Err(MnmlHttpError::InvalidCode);
}
if name.len() == 0 { if name.len() == 0 {
return Err(MnmlHttpError::AccountNameNotProvided); return Err(MnmlHttpError::AccountNameNotProvided);
} }

View File

@ -52,8 +52,6 @@ pub enum MnmlHttpError {
PasswordUnacceptable, PasswordUnacceptable,
#[fail(display="incorrect token. refresh or logout of existing sessions")] #[fail(display="incorrect token. refresh or logout of existing sessions")]
TokenDoesNotMatch, TokenDoesNotMatch,
#[fail(display="invalid code. https://discord.gg/YJJgurM")]
InvalidCode,
} }
impl From<bcrypt::BcryptError> for MnmlHttpError { impl From<bcrypt::BcryptError> for MnmlHttpError {
@ -129,7 +127,6 @@ impl From<MnmlHttpError> for IronError {
MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest), MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest),
MnmlHttpError::PasswordNotMatch | MnmlHttpError::PasswordNotMatch |
MnmlHttpError::InvalidCode |
MnmlHttpError::TokenDoesNotMatch | MnmlHttpError::TokenDoesNotMatch |
MnmlHttpError::Unauthorized => (m_err.compat(), status::Unauthorized), MnmlHttpError::Unauthorized => (m_err.compat(), status::Unauthorized),
@ -211,7 +208,6 @@ fn token_res(token: String) -> Response {
struct RegisterBody { struct RegisterBody {
name: String, name: String,
password: String, password: String,
code: String,
} }
fn register(req: &mut Request) -> IronResult<Response> { fn register(req: &mut Request) -> IronResult<Response> {
@ -224,7 +220,7 @@ fn register(req: &mut Request) -> IronResult<Response> {
let db = state.pool.get().or(Err(MnmlHttpError::DbError))?; let db = state.pool.get().or(Err(MnmlHttpError::DbError))?;
let mut tx = db.transaction().or(Err(MnmlHttpError::DbError))?; let mut tx = db.transaction().or(Err(MnmlHttpError::DbError))?;
match account::create(&params.name, &params.password, &params.code, &mut tx) { match account::create(&params.name, &params.password, &mut tx) {
Ok(token) => { Ok(token) => {
tx.commit().or(Err(MnmlHttpError::ServerError))?; tx.commit().or(Err(MnmlHttpError::ServerError))?;
Ok(token_res(token)) Ok(token_res(token))

View File

@ -797,6 +797,25 @@ pub fn instance_game_finished(tx: &mut Transaction, game: &Game, instance_id: Uu
Ok(()) Ok(())
} }
pub fn demo() -> Result<Vec<Player>, Error> {
let bot = bot_player();
// generate bot imgs for the client to see
for c in bot.constructs.iter() {
img::molecular_write(c.img)?;
};
let bot2 = bot_player();
// generate bot imgs for the client to see
for c in bot2.constructs.iter() {
img::molecular_write(c.img)?;
};
Ok(vec![bot, bot2])
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -27,3 +27,4 @@ pub fn bot_player() -> Player {
let constructs = instance_mobs(bot_id); let constructs = instance_mobs(bot_id);
Player::new(bot_id, &name(), constructs).set_bot(true) Player::new(bot_id, &name(), constructs).set_bot(true)
} }

View File

@ -21,10 +21,12 @@ use account;
use construct::{Construct}; use construct::{Construct};
use events::{Event}; use events::{Event};
use game::{Game, game_state, game_skill, game_skill_clear, game_ready}; use game::{Game, game_state, game_skill, game_skill_clear, game_ready};
use instance::{Instance, instance_state, instance_practice, instance_ready, instance_abandon}; use instance::{Instance, instance_state, instance_practice, instance_ready, instance_abandon, demo};
use item::{Item, ItemInfoCtr, item_info}; use item::{Item, ItemInfoCtr, item_info};
use mtx; use mtx;
use mail; use mail;
use player::{Player};
use payments; use payments;
use mail::Email; use mail::Email;
use pg::{Db}; use pg::{Db};
@ -41,6 +43,8 @@ pub enum RpcMessage {
AccountInstances(Vec<Instance>), AccountInstances(Vec<Instance>),
AccountShop(mtx::Shop), AccountShop(mtx::Shop),
Demo(Vec<Player>),
ConstructSpawn(Construct), ConstructSpawn(Construct),
GameState(Game), GameState(Game),
ItemInfo(ItemInfoCtr), ItemInfo(ItemInfoCtr),
@ -271,6 +275,8 @@ impl Handler for Connection {
// tx should do nothing // tx should do nothing
tx.commit().unwrap(); tx.commit().unwrap();
} else {
self.ws.send(RpcMessage::Demo(demo().unwrap())).unwrap();
} }
Ok(()) Ok(())