Merge branch 'master' of ssh://cryps.gg:40022/~/cryps

This commit is contained in:
Mashy 2019-04-08 14:19:05 +10:00
commit 5aa9a1fa68
13 changed files with 276 additions and 115 deletions

BIN
client/assets/icons/726.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -10,7 +10,11 @@ html, body, .cryps {
font-family: 'Jura'; font-family: 'Jura';
color: whitesmoke; color: whitesmoke;
font-size: 16pt; font-size: 16pt;
user-select: none; user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
/* this is the sweet nectar to keep it full page*/ /* this is the sweet nectar to keep it full page*/
height: 99%; height: 99%;
@ -395,33 +399,50 @@ header {
min-width: 300px; min-width: 300px;
} }
/*
INFO
*/
.thresholds { .thresholds {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: left; justify-content: left;
} }
.info-stats { .info-cryp .skills {
display: flex;
}
.info-cryp .skills .cryp-skill-btn {
border: 1px solid whitesmoke;
}
.info-cryp .stats, .info-cryp .specs {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
justify-content: space-around; justify-content: space-around;
} }
.info-stats .speed { .info-cryp .stats .speed {
flex: 1 0 100%; flex: 1 0 100%;
} }
.info-stats figure { .info-cryp .stats figure {
flex: 0 0 30%; flex: 0 0 30%;
border: 0; border: 0;
margin: 1em 0; margin: 1em 0;
text-align: center; text-align: center;
} }
.info-stats .stat-icon { .info-cryp .stats .stat-icon {
height: 2.5em; height: 2.5em;
} }
.info-cryp .specs figure {
border: 0;
margin: 1em 0;
text-align: center;
}
/* CRYP BOX */ /* CRYP BOX */
.cryp-box { .cryp-box {
@ -456,7 +477,7 @@ header {
flex-flow: column; flex-flow: column;
} }
.stats { .cryp-box .stats {
flex: 0 0 20%; flex: 0 0 20%;
width: 100%; width: 100%;
display: flex; display: flex;
@ -492,7 +513,7 @@ header {
border-right-width: 0px; border-right-width: 0px;
} }
.cryp-skill-btn:first-child { .cryp-list .skills .cryp-skill-btn:first-child {
border-top-width: 0; border-top-width: 0;
} }
@ -581,6 +602,10 @@ header {
order: 99; order: 99;
} }
header {
font-size: 0.5em;
}
.header-username { .header-username {
display: none; display: none;
} }
@ -636,8 +661,17 @@ header {
flex: 1; flex: 1;
} }
.info-cryp {
text-align: center;
}
.cryp-box { .cryp-box {
margin: 0.5em; margin: 0;
border-left-width: 0px;
}
.cryp-box:first-child {
border-left-width: 1px;
} }
.spawn-btn button { .spawn-btn button {
@ -685,7 +719,7 @@ header {
height: 1em; height: 1em;
} }
.stats figcaption { .cryp-list .stats figcaption {
display: none; display: none;
} }

View File

@ -8,7 +8,7 @@
<meta name=apple-mobile-web-app-status-bar-style content=black> <meta name=apple-mobile-web-app-status-bar-style content=black>
<meta name="description" content="cryps.gg - mnml pvp atbs"> <meta name="description" content="cryps.gg - mnml pvp atbs">
<meta name="author" content="ntr@smokestack.io"> <meta name="author" content="ntr@smokestack.io">
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.webmanifest">
<link rel="stylesheet" href="./node_modules/izitoast/dist/css/iziToast.min.css"></script> <link rel="stylesheet" href="./node_modules/izitoast/dist/css/iziToast.min.css"></script>
<link href="https://fonts.googleapis.com/css?family=Jura" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Jura" rel="stylesheet">
<link rel="stylesheet" href="assets/normalize.css"> <link rel="stylesheet" href="assets/normalize.css">
@ -17,5 +17,14 @@
</head> </head>
<body> <body>
</body> </body>
<script>
// Check that service workers are registered
if ('serviceWorker' in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener('load', () => {
navigator.serviceWorker.register('./service.worker.js');
});
}
</script>
<script src="./index.js"></script> <script src="./index.js"></script>
</html> </html>

View File

@ -1,7 +0,0 @@
{
"short_name": "cryps.gg",
"name": "cryps.gg - mnml pvp atbs",
"start_url": "/index.html",
"display": "fullscreen",
"orientation": "portrait"
}

View File

@ -0,0 +1,22 @@
{
"name": "cryps.gg - mnml pvp atbs",
"description": "cryps.gg - mnml pvp atbs",
"short_name": "cryps.gg",
"icons": [
{
"src": "./assets/icons/726.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "./assets/icons/726.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/index.html",
"display": "fullscreen",
"orientation": "portrait",
"theme_color": "#000000",
"background_color": "#000000"
}

13
client/service.worker.js Normal file
View File

@ -0,0 +1,13 @@
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});

View File

@ -1,104 +1,143 @@
const preact = require('preact'); const preact = require('preact');
const { ITEMS: { SKILLS, SPECS, COLOURS } } = require('./constants'); const range = require('lodash/range');
const { COLOUR_ICONS, STATS } = require('../utils');
const { ITEMS: { SKILLS, COLOURS, SPECS: SPEC_CONSTANT } } = require('./constants');
const { COLOUR_ICONS, STATS, SPECS } = require('../utils');
function Info(args) { function Info(args) {
const { const {
activeCryp,
info, info,
sendUnequip, sendUnequip,
instance, instance,
} = args; } = args;
if (!info.length) return (<div className="instance-info">&nbsp;</div>);
let red = 0; let blue = 0; let green = 0;
instance.cryps.forEach(cryp => {
red += cryp.colours.red;
blue += cryp.colours.blue;
green += cryp.colours.green;
});
const teamColours = { red, blue, green };
const [type, value] = info;
if (type === 'item') {
let itemDetails;
if (SKILLS[value]) {
itemDetails = SKILLS[value];
} else if (SPECS[value]) {
itemDetails = SPECS[value];
} else if (COLOURS[value]) {
itemDetails = COLOURS[value];
}
return (
<div className="instance-info">
{value} - {itemDetails.description}
</div>
);
}
if (type === 'skill') { function infoVar([type, value]) {
return ( let red = 0; let blue = 0; let green = 0;
<div className="instance-info"> instance.cryps.forEach(cryp => {
<div> red += cryp.colours.red;
<div> {value.skill} </div> blue += cryp.colours.blue;
<div> {SKILLS[value.skill].description} </div> green += cryp.colours.green;
<button onClick={() => sendUnequip(value.cryp.id, value.skill)}> });
const teamColours = { red, blue, green };
if (type === 'item') {
let itemDetails;
if (SKILLS[value]) {
itemDetails = SKILLS[value];
} else if (SPEC_CONSTANT[value]) {
itemDetails = SPEC_CONSTANT[value];
} else if (COLOURS[value]) {
itemDetails = COLOURS[value];
}
return (
<div className="info-var">
{value} - {itemDetails.description}
</div>
);
}
if (type === 'skill') {
return (
<div className="info-skill">
<div> {value.skill.skill} </div>
<div> {SKILLS[value.skill.skill].description} </div>
<button onClick={() => sendUnequip(value.cryp.id, value.skill.skill)}>
unequip unequip
</button> </button>
</div> </div>
</div> );
); }
}
function thresholds(t, spec) { function thresholds(t, spec) {
return (
SPECS[spec].colours.map((c, i) => (
<figure key={i} alt={c.colour}>
{COLOUR_ICONS[c].svg(`stat-icon ${COLOUR_ICONS[c].colour}`)}
<figcaption>{Math.min(teamColours[c], t)} / {t}</figcaption>
</figure>
))
);
}
if (type === 'spec') {
const breaks = SPECS[value.spec].thresholds ? SPECS[value.spec].thresholds.map((t, i) => {
const threshold = thresholds(t, value.spec);
return ( return (
<div className="thresholds" key={i} alt={t}> SPEC_CONSTANT[spec].colours.map((c, i) => (
{threshold} <figure key={i} alt={c.colour}>
{COLOUR_ICONS[c].svg(`stat-icon ${COLOUR_ICONS[c].colour}`)}
<figcaption>{Math.min(teamColours[c], t)} / {t}</figcaption>
</figure>
))
);
}
if (type === 'spec') {
const breaks = SPEC_CONSTANT[value.spec].thresholds ? SPEC_CONSTANT[value.spec].thresholds.map((t, i) => {
const threshold = thresholds(t, value.spec);
return (
<div className="thresholds" key={i} alt={t}>
{threshold}
</div>
);
}) : null;
return (
<div className="info-spec">
<div>
<div> {value.spec} </div>
<div> {SPEC_CONSTANT[value.spec].description} </div>
{breaks}
</div>
<button onClick={() => sendUnequip(value.cryp.id, value.spec)}>
unequip
</button>
</div> </div>
); );
}) : null; }
return (
<div className="instance-info">
<div>
<div> {value.spec} </div>
<div> {SPECS[value.spec].description} </div>
{breaks}
</div>
<button onClick={() => sendUnequip(value.cryp.id, value.spec)}>
unequip
</button>
</div>
);
} }
if (type === 'cryp') { function infoCrypElement(cryp) {
const cryp = value; // onClick={() => setInfo('skill', { skill: s, cryp })}
const skills = range(0, 4).map(i => {
const s = cryp.skills[i]
? cryp.skills[i].skill
: (<span>&nbsp;</span>);
return <button key={i} className="cryp-skill-btn right" >{s}</button>;
});
const stats = Object.values(STATS).map((s, j) => ( const stats = Object.values(STATS).map((s, j) => (
<figure key={j} alt={s.stat} className={s.stat}> <figure key={j} alt={s.stat} className={s.stat}>
{s.svg(`stat-icon ${s.colour}`)} {s.svg(`stat-icon ${s.colour}`)}
<figcaption>{cryp[s.stat].value}</figcaption> <figcaption>{cryp[s.stat].value}</figcaption>
</figure> </figure>
)); ));
const specs = cryp.specs.map((s, i) => (
<figure key={i}>
{SPECS[s].svg(`stat-icon ${SPECS[s].colour}`)}
<figcaption>{SPECS[s].caption}</figcaption>
</figure>
));
return ( return (
<div className="instance-info"> <div className="info-cryp">
<h5>{cryp.name}</h5> <h5>{cryp.name}</h5>
<div className="info-stats"> <div className="stats">
{stats} {stats}
</div> </div>
<div className="specs">
{specs}
</div>
<div className="skills">
{skills}
</div>
</div> </div>
); );
} }
const infoCryp = activeCryp
? infoCrypElement(activeCryp)
: null;
const otherInfo = info.length
? infoVar(info)
: null;
return (
<div className="instance-info">
{infoCryp}
{otherInfo}
</div>
);
} }
module.exports = Info; module.exports = Info;

View File

@ -6,12 +6,23 @@ const Info = require('./info.component');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { info, ws, instance } = state; const {
activeCryp,
info,
ws,
instance,
} = state;
function sendUnequip(crypId, item) { function sendUnequip(crypId, item) {
return ws.sendVboxUnequip(instance.instance, crypId, item); return ws.sendVboxUnequip(instance.instance, crypId, item);
} }
return { info, sendUnequip, instance }; return {
activeCryp,
info,
sendUnequip,
instance,
};
} }
/* /*
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {

View File

@ -7,15 +7,30 @@ const VboxContainer = require('./vbox.container');
const InfoContainer = require('./info.container'); const InfoContainer = require('./info.container');
const molecule = require('./molecule'); const molecule = require('./molecule');
const shapes = require('./shapes'); const { SPECS } = require('../utils');
const { STATS, SPECS } = require('../utils');
function Cryp(props) {
const {
cryp,
sendVboxApply,
setInfo,
activeVar,
setActiveCryp,
} = props;
function Cryp(cryp, sendVboxApply, setInfo, activeVar) {
const skills = range(0, 4).map(i => { const skills = range(0, 4).map(i => {
const s = cryp.skills[i] const skill = cryp.skills[i];
? cryp.skills[i].skill const s = skill
? skill.skill
: (<span>&nbsp;</span>); : (<span>&nbsp;</span>);
return <button key={i} className="cryp-skill-btn right" onClick={() => setInfo('skill', { skill: s, cryp })}>{s}</button>;
function skillClick() {
if (!skill) return false;
setInfo('skill', { skill, cryp });
return setActiveCryp(cryp);
}
return <button key={i} className="cryp-skill-btn right" onClick={skillClick} >{s}</button>;
}); });
// needed for ondrop to fire // needed for ondrop to fire
@ -36,17 +51,22 @@ function Cryp(cryp, sendVboxApply, setInfo, activeVar) {
e.preventDefault(); e.preventDefault();
if (activeVar !== null) return sendVboxApply(cryp.id, activeVar); if (activeVar !== null) return sendVboxApply(cryp.id, activeVar);
document.getElementsByClassName('instance-info')[0].scrollIntoView(); return setActiveCryp(cryp);
return setInfo('cryp', cryp);
} }
const specs = cryp.specs.map((s, i) => ( const specs = cryp.specs.map((s, i) => {
<figure key={i} onClick={() => setInfo('spec', { spec: s, cryp })}> function specClick() {
{SPECS[s].svg(`stat-icon ${SPECS[s].colour}`)} setActiveCryp(cryp);
<figcaption>{SPECS[s].caption}</figcaption> setInfo('spec', { spec: s, cryp });
</figure> }
)); return (
<figure key={i} onClick={specClick}>
{SPECS[s].svg(`stat-icon ${SPECS[s].colour}`)}
<figcaption>{SPECS[s].caption}</figcaption>
</figure>
);
});
const cTotal = cryp.colours.red + cryp.colours.blue + cryp.colours.green; const cTotal = cryp.colours.red + cryp.colours.blue + cryp.colours.green;
const colours = mapValues(cryp.colours, c => { const colours = mapValues(cryp.colours, c => {
if (cTotal === 0) return 245; if (cTotal === 0) return 245;
@ -84,19 +104,27 @@ function InstanceComponent(args) {
// account, // account,
instance, instance,
quit, quit,
// clearInfo,
sendInstanceReady, sendInstanceReady,
sendVboxApply, sendVboxApply,
setInfo, setInfo,
activeVar, activeVar,
setActiveVar, setActiveVar,
setActiveCryp,
} = args; } = args;
if (!instance) return <div>...</div>; if (!instance) return <div>...</div>;
const cryps = instance.cryps.map((c, i) => Cryp(c, sendVboxApply, setInfo, activeVar)); const cryps = instance.cryps.map((c, i) => Cryp({
cryp: c, sendVboxApply, setInfo, activeVar, setActiveCryp,
}));
function onClick(e) {
setActiveVar(null);
}
return ( return (
<main className="instance" onClick={() => setActiveVar(null)} > <main className="instance" onClick={onClick} >
<div className="instance-hdr"> <div className="instance-hdr">
<button <button
className="instance-btn instance-ui-btn menu-btn left" className="instance-btn instance-ui-btn menu-btn left"

View File

@ -19,7 +19,7 @@ const addState = connect(
return { instance, account, sendInstanceReady, sendVboxApply, activeVar }; return { instance, account, sendInstanceReady, sendVboxApply, activeVar };
}, },
function receiveDispatch(dispatch, { instance, combiner }) { function receiveDispatch(dispatch) {
function quit() { function quit() {
dispatch(actions.setInstance(null)); dispatch(actions.setInstance(null));
} }
@ -32,7 +32,15 @@ const addState = connect(
dispatch(actions.setActiveVar(value)); dispatch(actions.setActiveVar(value));
} }
return { quit, setInfo, setActiveVar }; function setActiveCryp(value) {
dispatch(actions.setActiveCryp(value));
}
function clearInfo() {
return dispatch(actions.setInfo([]));
}
return { quit, clearInfo, setInfo, setActiveVar, setActiveCryp };
} }
); );

View File

@ -88,14 +88,11 @@ function Vbox(args) {
let boundTimer; let boundTimer;
function boundTouchStart(e, i) { function boundTouchStart(e, i) {
e.preventDefault(); // e.preventDefault();
e.stopPropagation(); // e.stopPropagation();
boundTimer = (setTimeout(() => { boundTimer = (setTimeout(() => {
const insert = combiner.findIndex(j => j === null);
if (insert === -1) return setCombiner([i, null, null]);
combiner[insert] = i;
boundTimer = null; boundTimer = null;
return setCombiner(combiner); return setActiveVar(i);
}, LONG_TOUCH_TIME)); }, LONG_TOUCH_TIME));
return true; return true;
} }
@ -105,7 +102,12 @@ function Vbox(args) {
clearTimeout(boundTimer); clearTimeout(boundTimer);
if (reclaiming && i) sendVboxReclaim(i); if (reclaiming && i) sendVboxReclaim(i);
else if (vbox.bound[i]) setActiveVar(i); else if (vbox.bound[i]) {
const insert = combiner.findIndex(j => j === null);
if (insert === -1) return setCombiner([i, null, null]);
combiner[insert] = i;
return setCombiner(combiner);
}
} }
return true; return true;
} }

View File

@ -6,7 +6,7 @@ const Vbox = require('./vbox.component');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { ws, instance, combiner, reclaiming, activeVar } = state; const { ws, instance, combiner, reclaiming, activeVar, info } = state;
function sendVboxDiscard() { function sendVboxDiscard() {
return ws.sendVboxDiscard(instance.instance); return ws.sendVboxDiscard(instance.instance);
@ -29,6 +29,7 @@ const addState = connect(
combiner, combiner,
reclaiming, reclaiming,
activeVar, activeVar,
info,
sendVboxAccept, sendVboxAccept,
sendVboxDiscard, sendVboxDiscard,
sendVboxReclaim, sendVboxReclaim,

View File

@ -19,6 +19,7 @@
*CLIENT* *CLIENT*
* general * general
* icons change with % * icons change with %
* colour vbox icons
* instance * instance
* cryp / vbox page separation * cryp / vbox page separation