better wip hey
This commit is contained in:
parent
faff221ca6
commit
7e8e320c7d
@ -35,6 +35,7 @@
|
||||
*CLIENT*
|
||||
reconnect based on time delta
|
||||
menu footer
|
||||
fix refresh button
|
||||
|
||||
|
||||
*SERVER*
|
||||
|
||||
@ -61,6 +61,7 @@ module.exports = {
|
||||
"react/jsx-uses-vars": 1,
|
||||
"react/prefer-stateless-function": 1,
|
||||
"react/prop-types": 0,
|
||||
"react/no-unknown-property": 0,
|
||||
|
||||
// airbnb copypasta
|
||||
// enforces getter/setter pairs in objects
|
||||
|
||||
@ -79,8 +79,13 @@
|
||||
stroke-width: 2px;
|
||||
stroke: whitesmoke;
|
||||
|
||||
/* some stupid bug in chrome makes it fill the entire screen */
|
||||
}
|
||||
|
||||
/* some stupid bug in chrome makes it fill the entire screen */
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
#targeting {
|
||||
max-height: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
.resolving #targeting {
|
||||
|
||||
@ -418,4 +418,4 @@ button.equipping {
|
||||
}
|
||||
|
||||
/* Mobile Nav*/
|
||||
.instance .nav-btn { display: none; }
|
||||
.instance-nav { display: none; }
|
||||
|
||||
@ -2,12 +2,10 @@
|
||||
.instance {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: min-content, min-content, min-content, 1fr;
|
||||
grid-template-rows: min-content, 1fr;
|
||||
grid-template-areas:
|
||||
"top"
|
||||
"controls"
|
||||
"vbox"
|
||||
"constructs"
|
||||
"constructs";
|
||||
}
|
||||
|
||||
.instance .nav-btn { display: initial; }
|
||||
@ -131,4 +129,20 @@
|
||||
.instance-construct:last-child {
|
||||
border-left: 1px solid #222;
|
||||
}
|
||||
|
||||
.instance-nav {
|
||||
display: flex;
|
||||
grid-area: nav;
|
||||
margin-right: 0;
|
||||
border-top: 2px solid #444;
|
||||
}
|
||||
|
||||
.instance-nav button {
|
||||
font-size: 150%;
|
||||
border-right: 2px solid #444;
|
||||
}
|
||||
|
||||
.instance-nav button:last-child {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@ html, body, #mnml {
|
||||
/*padding: 0 20%;*/
|
||||
|
||||
/* stops inspector going skitz*/
|
||||
/*overflow: hidden;*/
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
html {
|
||||
@ -70,10 +70,11 @@ figure {
|
||||
padding: 0 2em;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 8fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
grid-template-rows: min-content 1fr min-content;
|
||||
grid-template-areas:
|
||||
"hd hd"
|
||||
"nav main";
|
||||
"nav main"
|
||||
"nav footer";
|
||||
}
|
||||
|
||||
nav {
|
||||
@ -145,6 +146,7 @@ button, input {
|
||||
letter-spacing: 0.25em;
|
||||
box-sizing: border-box;
|
||||
font-size: 100%;
|
||||
flex: 1;
|
||||
|
||||
/*the transitions */
|
||||
transition-property: color;
|
||||
@ -159,22 +161,6 @@ button:hover, button:focus {
|
||||
border-color: whitesmoke;
|
||||
}
|
||||
|
||||
button.right[disabled]:hover, button.left[disabled]:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
button.top:hover, button.top:focus {
|
||||
box-shadow: inset 0 0.25em 0 0 whitesmoke;
|
||||
}
|
||||
|
||||
button.right:hover, button.right:focus {
|
||||
box-shadow: inset -0.5em 0 0 0 whitesmoke;
|
||||
}
|
||||
|
||||
button.left:hover, button.left:focus {
|
||||
box-shadow: inset 0.5em 0 0 0 whitesmoke;
|
||||
}
|
||||
|
||||
a {
|
||||
color: whitesmoke;
|
||||
font-size: 150%;
|
||||
@ -313,18 +299,20 @@ header {
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.header-username {
|
||||
letter-spacing: 0.05em;
|
||||
display: inline;
|
||||
.header-status {
|
||||
margin: 1em 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-status {
|
||||
text-align: right;
|
||||
.header-username {
|
||||
letter-spacing: 0.05em;
|
||||
flex: 1;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.header-status svg {
|
||||
margin: 0.5em 0 0 1em;
|
||||
height: 1.5em;
|
||||
height: 1em;
|
||||
background-color: black;
|
||||
stroke: whitesmoke;
|
||||
}
|
||||
@ -359,29 +347,14 @@ header {
|
||||
TEAM
|
||||
*/
|
||||
|
||||
.menu-constructs {
|
||||
.team {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-rows: min-content min-content;
|
||||
|
||||
grid-template-areas:
|
||||
"top"
|
||||
"team";
|
||||
}
|
||||
|
||||
.constructs-list {
|
||||
max-height: 100%;
|
||||
margin-top: 0.5em;
|
||||
grid-area: team;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-auto-rows: 1fr;
|
||||
grid-gap: 0.5em;
|
||||
grid-gap: 1em;
|
||||
grid-template-columns: repeat(auto-fill,minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.menu-construct {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid black;
|
||||
|
||||
display: flex;
|
||||
@ -544,10 +517,11 @@ main .top button {
|
||||
max-height: 0.25em;
|
||||
|
||||
border: none;
|
||||
margin: 1em 0;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
||||
|
||||
.timer {
|
||||
flex: 1 0 100%;
|
||||
background: whitesmoke;
|
||||
transition-property: all;
|
||||
transition-duration: 0.5s;
|
||||
@ -559,6 +533,33 @@ main .top button {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
grid-area: footer;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
footer button {
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: #222;
|
||||
}
|
||||
|
||||
footer button:disabled {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
footer button:not(:last-child) {
|
||||
background: #222;
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
footer button .ready {
|
||||
background: forestgreen;
|
||||
color: black;
|
||||
}
|
||||
|
||||
@media (max-height: 900px), (max-width: 1500px) {
|
||||
#mnml {
|
||||
font-size: 75%;
|
||||
@ -569,7 +570,6 @@ main .top button {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Nav*/
|
||||
#nav-btn {
|
||||
#nav-btn, #instance-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
#mnml {
|
||||
font-size: 8pt;
|
||||
padding: 0;
|
||||
grid-template-columns: min-content 1fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content;
|
||||
grid-template-areas:
|
||||
"tnav hd "
|
||||
"main main";
|
||||
"main"
|
||||
"footer";
|
||||
}
|
||||
|
||||
#mnml button {
|
||||
@ -21,9 +21,8 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
#nav-btn {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em;
|
||||
#nav-btn, #instance-nav {
|
||||
display: unset;
|
||||
}
|
||||
|
||||
#mnml.nav-visible nav {
|
||||
@ -35,6 +34,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
36
client/src/components/footer.jsx
Normal file
36
client/src/components/footer.jsx
Normal file
@ -0,0 +1,36 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('./../actions');
|
||||
|
||||
const TeamFooter = require('./team.footer');
|
||||
const ListFooter = require('./list.footer');
|
||||
const InstanceFooter = require('./instance.footer');
|
||||
const GameFooter = require('./game.footer');
|
||||
|
||||
const addState = connect(
|
||||
({ nav, instance, game }) => {
|
||||
return { nav, instance, game };
|
||||
},
|
||||
dispatch => ({
|
||||
setShowNav: v => dispatch(actions.setShowNav(v)),
|
||||
})
|
||||
);
|
||||
|
||||
function renderHeader(args) {
|
||||
const {
|
||||
nav,
|
||||
instance,
|
||||
game,
|
||||
} = args;
|
||||
|
||||
if (instance) return <InstanceFooter />;
|
||||
if (game) return <GameFooter />;
|
||||
|
||||
if (nav === 'team') return <TeamFooter />;
|
||||
if (nav === 'list') return <ListFooter />;
|
||||
}
|
||||
|
||||
|
||||
module.exports = addState(renderHeader);
|
||||
@ -1,122 +0,0 @@
|
||||
const preact = require('preact');
|
||||
const GameConstruct = require('./game.construct');
|
||||
const Targeting = require('./targeting.arrows');
|
||||
|
||||
function GamePanel(props) {
|
||||
const {
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
setActiveSkill,
|
||||
setActiveConstruct,
|
||||
sendInstanceState,
|
||||
sendGameReady,
|
||||
skip,
|
||||
quit,
|
||||
} = props;
|
||||
|
||||
if (!game) return <div>...</div>;
|
||||
|
||||
function actionClick() {
|
||||
if (game.phase === 'Finish') {
|
||||
sendInstanceState(game.instance);
|
||||
quit();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (resolution) {
|
||||
return skip();
|
||||
}
|
||||
|
||||
return sendGameReady();
|
||||
}
|
||||
|
||||
const otherTeams = game.players.filter(t => t.id !== account.id);
|
||||
const playerTeam = game.players.find(t => t.id === account.id);
|
||||
|
||||
let actionText = 'Ready';
|
||||
let actionStyles = 'instance-btn instance-ui-btn right';
|
||||
if (game.phase === 'Finish') actionText = 'Done';
|
||||
if (resolution) actionText = 'Skip';
|
||||
if (actionText === 'Ready' && playerTeam.ready) actionStyles += ' ready';
|
||||
|
||||
const header = (
|
||||
<div className="top">
|
||||
<button
|
||||
className={actionStyles}
|
||||
onClick={() => actionClick()}>
|
||||
{actionText}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
function findConstruct(id) {
|
||||
const team = game.players.find(t => t.constructs.find(c => c.id === id));
|
||||
if (team) return team.constructs.find(c => c.id === id);
|
||||
return null;
|
||||
}
|
||||
|
||||
const zero = Date.parse(game.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(game.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
const displayPct = resolution || game.phase === 'Finish'
|
||||
? 0
|
||||
: Math.min(timerPct, 100);
|
||||
|
||||
const displayColour = playerTeam.ready
|
||||
? 'forestgreen'
|
||||
: timerPct > 80
|
||||
? 'red'
|
||||
: 'whitesmoke';
|
||||
|
||||
const timerStyles = {
|
||||
width: `${displayPct}%`,
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div className="timer-container">
|
||||
<div className="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
function PlayerTeam(team) {
|
||||
const constructs = team.constructs.map((c, i) =>
|
||||
<GameConstruct key={c.id} i={i} construct={c} player={true} />);
|
||||
return (
|
||||
<div className="team player">
|
||||
{constructs}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OpponentTeam(team) {
|
||||
const constructs = team.constructs.map((c, i) =>
|
||||
<GameConstruct key={c.id} i={i} construct={c} player={false} />);
|
||||
return (
|
||||
<div className="team opponent">
|
||||
{constructs}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const gameClasses = `game ${resolution ? 'resolving': ''}`;
|
||||
|
||||
function gameClick(e) {
|
||||
e.stopPropagation();
|
||||
setActiveConstruct(null);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className={gameClasses} onClick={gameClick} >
|
||||
{header}
|
||||
{timer}
|
||||
{otherTeams.map(OpponentTeam)}
|
||||
<Targeting />
|
||||
{PlayerTeam(playerTeam, setActiveSkill)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = GamePanel;
|
||||
@ -1,81 +0,0 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const Game = require('./game.component');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
ws,
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
showLog,
|
||||
activeSkill,
|
||||
activeConstruct,
|
||||
} = state;
|
||||
|
||||
function selectSkillTarget(targetConstructId) {
|
||||
if (activeSkill) {
|
||||
return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendGameReady() {
|
||||
ws.sendGameReady(game.id);
|
||||
}
|
||||
|
||||
function sendInstanceState(instanceId) {
|
||||
if (!instanceId) return false;
|
||||
return ws.sendInstanceState(instanceId);
|
||||
}
|
||||
|
||||
// intercept self casting skills
|
||||
if (activeSkill && activeSkill.skill.self_targeting) {
|
||||
ws.sendGameSkill(game.id, activeSkill.constructId, null, activeSkill.skill.skill);
|
||||
}
|
||||
|
||||
return {
|
||||
game,
|
||||
showLog,
|
||||
account,
|
||||
resolution,
|
||||
activeSkill,
|
||||
activeConstruct,
|
||||
selectSkillTarget,
|
||||
sendInstanceState,
|
||||
sendGameReady,
|
||||
};
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function setActiveSkill(constructId, skill) {
|
||||
dispatch(actions.setActiveSkill(constructId, skill));
|
||||
// particlesJS(`particles-${constructId}`, config);
|
||||
}
|
||||
|
||||
function setActiveConstruct(construct) {
|
||||
dispatch(actions.setActiveConstruct(construct));
|
||||
}
|
||||
|
||||
function quit() {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
}
|
||||
|
||||
function toggleLog(v) {
|
||||
dispatch(actions.setShowLog(v));
|
||||
}
|
||||
|
||||
function skip() {
|
||||
dispatch(actions.setSkip(true));
|
||||
}
|
||||
|
||||
return { setActiveSkill, setActiveConstruct, quit, toggleLog, skip };
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
module.exports = addState(Game);
|
||||
136
client/src/components/game.footer.jsx
Normal file
136
client/src/components/game.footer.jsx
Normal file
@ -0,0 +1,136 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
ws,
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
showNav,
|
||||
} = state;
|
||||
|
||||
function sendGameReady() {
|
||||
ws.sendGameReady(game.id);
|
||||
}
|
||||
|
||||
function sendInstanceState(instanceId) {
|
||||
if (!instanceId) return false;
|
||||
return ws.sendInstanceState(instanceId);
|
||||
}
|
||||
|
||||
return {
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
sendInstanceState,
|
||||
sendGameReady,
|
||||
showNav,
|
||||
};
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function quit() {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
}
|
||||
|
||||
function skip() {
|
||||
dispatch(actions.setSkip(true));
|
||||
}
|
||||
|
||||
function setShowNav(v) {
|
||||
return dispatch(actions.setShowNav(v));
|
||||
}
|
||||
|
||||
return { setShowNav, quit, skip };
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
function GameFooter(props) {
|
||||
const {
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
showNav,
|
||||
|
||||
quit,
|
||||
skip,
|
||||
setShowNav,
|
||||
sendGameReady,
|
||||
sendInstanceState,
|
||||
} = props;
|
||||
|
||||
if (!game) {
|
||||
return (
|
||||
<footer id="footer">
|
||||
<button id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
const playerTeam = game.players.find(t => t.id === account.id);
|
||||
|
||||
function actionClick() {
|
||||
if (game.phase === 'Finish') {
|
||||
sendInstanceState(game.instance);
|
||||
quit();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (resolution) {
|
||||
return skip();
|
||||
}
|
||||
|
||||
return sendGameReady();
|
||||
}
|
||||
|
||||
let actionText = 'Ready';
|
||||
if (game.phase === 'Finish') actionText = 'Done';
|
||||
if (resolution) actionText = 'Skip';
|
||||
const ready = (actionText === 'Ready' && playerTeam.ready)
|
||||
? 'ready'
|
||||
: '';
|
||||
|
||||
const zero = Date.parse(game.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(game.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
const displayPct = resolution || game.phase === 'Finish'
|
||||
? 0
|
||||
: Math.min(timerPct, 100);
|
||||
|
||||
const displayColour = playerTeam.ready
|
||||
? 'forestgreen'
|
||||
: timerPct > 80
|
||||
? 'red'
|
||||
: 'whitesmoke';
|
||||
|
||||
const timerStyles = {
|
||||
width: `${displayPct}%`,
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div className="timer-container">
|
||||
<div className="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<footer>
|
||||
{timer}
|
||||
<button
|
||||
className={ready}
|
||||
onClick={() => actionClick()}>
|
||||
{actionText}
|
||||
</button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(GameFooter);
|
||||
107
client/src/components/game.jsx
Normal file
107
client/src/components/game.jsx
Normal file
@ -0,0 +1,107 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const GameConstruct = require('./game.construct');
|
||||
const Targeting = require('./targeting.arrows');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
ws,
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
activeSkill,
|
||||
activeConstruct,
|
||||
} = state;
|
||||
|
||||
function selectSkillTarget(targetConstructId) {
|
||||
if (activeSkill) {
|
||||
return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// intercept self casting skills
|
||||
if (activeSkill && activeSkill.skill.self_targeting) {
|
||||
ws.sendGameSkill(game.id, activeSkill.constructId, null, activeSkill.skill.skill);
|
||||
}
|
||||
|
||||
return {
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
activeSkill,
|
||||
activeConstruct,
|
||||
selectSkillTarget,
|
||||
};
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function setActiveSkill(constructId, skill) {
|
||||
dispatch(actions.setActiveSkill(constructId, skill));
|
||||
// particlesJS(`particles-${constructId}`, config);
|
||||
}
|
||||
|
||||
function setActiveConstruct(construct) {
|
||||
dispatch(actions.setActiveConstruct(construct));
|
||||
}
|
||||
|
||||
return { setActiveSkill, setActiveConstruct };
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
function Game(props) {
|
||||
const {
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
setActiveSkill,
|
||||
setActiveConstruct,
|
||||
} = props;
|
||||
|
||||
if (!game) return <div>...</div>;
|
||||
|
||||
const otherTeams = game.players.filter(t => t.id !== account.id);
|
||||
const playerTeam = game.players.find(t => t.id === account.id);
|
||||
|
||||
function PlayerTeam(team) {
|
||||
const constructs = team.constructs.map((c, i) =>
|
||||
<GameConstruct key={c.id} i={i} construct={c} player={true} />);
|
||||
return (
|
||||
<div className="team player">
|
||||
{constructs}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OpponentTeam(team) {
|
||||
const constructs = team.constructs.map((c, i) =>
|
||||
<GameConstruct key={c.id} i={i} construct={c} player={false} />);
|
||||
return (
|
||||
<div className="team opponent">
|
||||
{constructs}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const gameClasses = `game ${resolution ? 'resolving': ''}`;
|
||||
|
||||
function gameClick(e) {
|
||||
e.stopPropagation();
|
||||
setActiveConstruct(null);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className={gameClasses} onClick={gameClick} >
|
||||
{otherTeams.map(OpponentTeam)}
|
||||
<Targeting />
|
||||
{PlayerTeam(playerTeam, setActiveSkill)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(Game);
|
||||
@ -1,15 +0,0 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const Header = require('./header.component');
|
||||
const actions = require('./../actions');
|
||||
|
||||
const addState = connect(
|
||||
({ account, ping, showNav }) => {
|
||||
return { account, ping, showNav };
|
||||
},
|
||||
dispatch => ({
|
||||
setShowNav: v => dispatch(actions.setShowNav(v)),
|
||||
})
|
||||
);
|
||||
|
||||
module.exports = addState(Header);
|
||||
@ -1,7 +1,9 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const { saw } = require('./shapes');
|
||||
const actions = require('./../actions');
|
||||
|
||||
function pingColour(ping) {
|
||||
if (ping < 100) return 'forestgreen';
|
||||
@ -9,8 +11,14 @@ function pingColour(ping) {
|
||||
return 'red';
|
||||
}
|
||||
|
||||
const addState = connect(
|
||||
({ account, ping, showNav }) => {
|
||||
return { account, ping };
|
||||
},
|
||||
);
|
||||
|
||||
function renderHeader(args) {
|
||||
const { account, ping, setShowNav, showNav } = args;
|
||||
const { account, ping } = args;
|
||||
|
||||
const accountStatus = account
|
||||
? (<div className="header-status">
|
||||
@ -22,14 +30,11 @@ function renderHeader(args) {
|
||||
|
||||
return (
|
||||
<header>
|
||||
<h1 className="header-title">
|
||||
<span id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</span>
|
||||
mnml.gg
|
||||
</h1>
|
||||
<h1 className="header-title">mnml.gg</h1>
|
||||
{accountStatus}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
module.exports = renderHeader;
|
||||
module.exports = addState(renderHeader);
|
||||
@ -10,13 +10,8 @@ const actions = require('../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, instance, player, account, nav } = state;
|
||||
|
||||
function sendInstanceReady() {
|
||||
return ws.sendInstanceReady(instance.id);
|
||||
}
|
||||
|
||||
return { player, instance, sendInstanceReady, nav };
|
||||
const { ws, instance, nav } = state;
|
||||
return { instance, nav };
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
@ -24,13 +19,8 @@ const addState = connect(
|
||||
return dispatch(actions.setInfo(c));
|
||||
}
|
||||
|
||||
function setNav(v) {
|
||||
return dispatch(actions.setNav(v));
|
||||
}
|
||||
|
||||
return {
|
||||
setInfo,
|
||||
setNav,
|
||||
};
|
||||
}
|
||||
);
|
||||
@ -38,62 +28,13 @@ const addState = connect(
|
||||
function Instance(args) {
|
||||
const {
|
||||
instance,
|
||||
player,
|
||||
sendInstanceReady,
|
||||
setInfo,
|
||||
|
||||
nav,
|
||||
setNav,
|
||||
} = args;
|
||||
|
||||
if (!instance) return false;
|
||||
|
||||
function hoverInfo(e, info) {
|
||||
e.stopPropagation();
|
||||
return setInfo(info);
|
||||
}
|
||||
|
||||
const rdyClasses = `instance-btn instance-ui-btn ${player.ready ? 'ready' : ''}`;
|
||||
const readyInfo = instance.phase === 'Lobby'
|
||||
? 'lobbyReady'
|
||||
: 'ready';
|
||||
const readyBtn = (
|
||||
<button
|
||||
className={rdyClasses}
|
||||
onMouseOver={e => hoverInfo(e, readyInfo)}
|
||||
onClick={() => sendInstanceReady()}>
|
||||
Ready
|
||||
</button>
|
||||
);
|
||||
|
||||
function navClick() {
|
||||
if (nav === 'vbox') return setNav('constructs');
|
||||
return setNav('vbox');
|
||||
}
|
||||
|
||||
const navBtn = (
|
||||
<button
|
||||
className="nav-btn"
|
||||
onClick={navClick}>
|
||||
{nav === 'vbox' ? 'Constructs' : 'Vbox'}
|
||||
</button>
|
||||
);
|
||||
|
||||
|
||||
const actionBtn = player
|
||||
? readyBtn
|
||||
: null;
|
||||
|
||||
// TIMER
|
||||
const zero = Date.parse(instance.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(instance.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
const timerStyles = {
|
||||
width: `${timerPct < 100 ? timerPct : 0}%`,
|
||||
background: player.ready ? 'forestgreen' : 'whitesmoke',
|
||||
};
|
||||
|
||||
function playerRound(id) {
|
||||
if (!instance.rounds.length) return null;
|
||||
return instance.rounds[instance.rounds.length - 1].find(r => r.player_ids.includes(id));
|
||||
@ -139,21 +80,10 @@ function Instance(args) {
|
||||
);
|
||||
}
|
||||
|
||||
const timer = (
|
||||
<div className="timer-container">
|
||||
<div className="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const instanceClasses = `instance ${nav === 'constructs' ? 'constructs-visible' : ''}`;
|
||||
|
||||
return (
|
||||
<main className={instanceClasses} onMouseOver={() => setInfo(null)} >
|
||||
<div className="top">
|
||||
{actionBtn}
|
||||
{timer}
|
||||
{navBtn}
|
||||
</div>
|
||||
<ScoreBoard />
|
||||
<Vbox />
|
||||
<InfoContainer />
|
||||
|
||||
126
client/src/components/instance.footer.jsx
Normal file
126
client/src/components/instance.footer.jsx
Normal file
@ -0,0 +1,126 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, instance, player, nav, showNav } = state;
|
||||
|
||||
function sendInstanceReady() {
|
||||
return ws.sendInstanceReady(instance.id);
|
||||
}
|
||||
|
||||
return { player, instance, sendInstanceReady, nav, showNav };
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function setShowNav(v) {
|
||||
return dispatch(actions.setShowNav(v));
|
||||
}
|
||||
|
||||
function setInfo(c) {
|
||||
return dispatch(actions.setInfo(c));
|
||||
}
|
||||
|
||||
function setNav(v) {
|
||||
return dispatch(actions.setNav(v));
|
||||
}
|
||||
|
||||
return {
|
||||
setInfo,
|
||||
setNav,
|
||||
setShowNav,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function Instance(args) {
|
||||
const {
|
||||
instance,
|
||||
player,
|
||||
nav,
|
||||
showNav,
|
||||
|
||||
setInfo,
|
||||
setNav,
|
||||
setShowNav,
|
||||
|
||||
sendInstanceReady,
|
||||
} = args;
|
||||
|
||||
if (!instance || !player) {
|
||||
return (
|
||||
<footer id="footer">
|
||||
<button id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function hoverInfo(e, info) {
|
||||
e.stopPropagation();
|
||||
return setInfo(info);
|
||||
}
|
||||
|
||||
const rdyClasses = `${player.ready ? 'ready' : ''}`;
|
||||
const readyInfo = instance.phase === 'Lobby'
|
||||
? 'lobbyReady'
|
||||
: 'ready';
|
||||
|
||||
const readyBtn = (
|
||||
<button
|
||||
className={rdyClasses}
|
||||
onMouseOver={e => hoverInfo(e, readyInfo)}
|
||||
onClick={() => sendInstanceReady()}>
|
||||
Ready
|
||||
</button>
|
||||
);
|
||||
|
||||
function navClick() {
|
||||
if (nav === 'vbox') return setNav('constructs');
|
||||
return setNav('vbox');
|
||||
}
|
||||
|
||||
const navBtn = instance.phase === 'InProgress'
|
||||
? (
|
||||
<button
|
||||
id="instance-nav"
|
||||
onClick={navClick}>
|
||||
{nav === 'vbox' ? 'Constructs' : 'Vbox'}
|
||||
</button>
|
||||
)
|
||||
: null;
|
||||
|
||||
const zero = Date.parse(instance.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(instance.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
|
||||
const displayColour = player.ready
|
||||
? 'forestgreen'
|
||||
: timerPct > 80
|
||||
? 'red'
|
||||
: 'whitesmoke';
|
||||
|
||||
const timerStyles = {
|
||||
width: `${timerPct}%`,
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div className="timer-container">
|
||||
<div className="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<footer id="footer">
|
||||
{timer}
|
||||
<button id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</button>
|
||||
{navBtn}
|
||||
{readyBtn}
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(Instance);
|
||||
47
client/src/components/list.footer.jsx
Normal file
47
client/src/components/list.footer.jsx
Normal file
@ -0,0 +1,47 @@
|
||||
const { connect } = require('preact-redux');
|
||||
const preact = require('preact');
|
||||
|
||||
const actions = require('./../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { showNav } = state;
|
||||
return { showNav };
|
||||
},
|
||||
function receiveDispatch(dispatch) {
|
||||
function navToTeam() {
|
||||
return dispatch(actions.setNav('team'));
|
||||
}
|
||||
|
||||
function setShowNav(v) {
|
||||
return dispatch(actions.setShowNav(v));
|
||||
}
|
||||
|
||||
return {
|
||||
navToTeam,
|
||||
setShowNav,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function ListFooter(args) {
|
||||
const {
|
||||
showNav,
|
||||
|
||||
navToTeam,
|
||||
setShowNav,
|
||||
} = args;
|
||||
|
||||
return (
|
||||
<footer>
|
||||
<button id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</button>
|
||||
<button
|
||||
className="instance-btn instance-ui-btn left"
|
||||
onClick={() => navToTeam()}>
|
||||
Change Constructs
|
||||
</button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(ListFooter);
|
||||
@ -37,15 +37,6 @@ const addState = connect(
|
||||
instanceList,
|
||||
};
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function navToTeam() {
|
||||
return dispatch(actions.setNav('team'));
|
||||
}
|
||||
return {
|
||||
navToTeam,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function List(args) {
|
||||
@ -57,7 +48,6 @@ function List(args) {
|
||||
sendInstanceJoin,
|
||||
sendInstanceList,
|
||||
instanceList,
|
||||
navToTeam,
|
||||
} = args;
|
||||
|
||||
function listElements() {
|
||||
@ -120,20 +110,8 @@ function List(args) {
|
||||
</div>
|
||||
);
|
||||
|
||||
const header = (
|
||||
<div className="top">
|
||||
<button
|
||||
className="instance-btn instance-ui-btn left"
|
||||
onClick={() => navToTeam()}>
|
||||
Select Constructs
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<main className="menu-instances">
|
||||
{header}
|
||||
<div className="construct-list">
|
||||
{constructPanels}
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@ const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const Login = require('./login');
|
||||
const GameContainer = require('./game.container');
|
||||
const Game = require('./game');
|
||||
const Instance = require('./instance.component');
|
||||
const Team = require('./team');
|
||||
const List = require('./list');
|
||||
@ -28,7 +28,7 @@ function Main(props) {
|
||||
}
|
||||
|
||||
if (game) {
|
||||
return <GameContainer />;
|
||||
return <Game />;
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const Header = require('./header.container');
|
||||
// const Header = require('./header');
|
||||
const Main = require('./main');
|
||||
const Nav = require('./nav');
|
||||
const Footer = require('./footer');
|
||||
|
||||
const addState = connect(
|
||||
state => ({ showNav: state.showNav })
|
||||
);
|
||||
|
||||
const Mnml = ({ showNav, setShowNav }) =>
|
||||
const Mnml = ({ showNav }) =>
|
||||
<div id="mnml" className={showNav ? 'nav-visible' : ''}>
|
||||
<Header />
|
||||
<Nav />
|
||||
<Main />
|
||||
<Footer />
|
||||
</div>;
|
||||
|
||||
module.exports = addState(Mnml);
|
||||
|
||||
@ -3,9 +3,17 @@ const preact = require('preact');
|
||||
const { Fragment } = require('preact');
|
||||
const actions = require('../actions');
|
||||
|
||||
const { saw } = require('./shapes');
|
||||
|
||||
const testGame = process.env.NODE_ENV === 'development' && require('./../test.game');
|
||||
const testInstance = process.env.NODE_ENV === 'development' && require('./../test.instance');
|
||||
|
||||
function pingColour(ping) {
|
||||
if (ping < 100) return 'forestgreen';
|
||||
if (ping < 200) return 'yellow';
|
||||
return 'red';
|
||||
}
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
@ -13,7 +21,8 @@ const addState = connect(
|
||||
account,
|
||||
instances,
|
||||
team,
|
||||
// constructs,
|
||||
ping,
|
||||
|
||||
game,
|
||||
} = state;
|
||||
|
||||
@ -34,6 +43,7 @@ const addState = connect(
|
||||
instances,
|
||||
team,
|
||||
game,
|
||||
ping,
|
||||
sendInstanceState,
|
||||
sendAccountInstances,
|
||||
sendInstanceList,
|
||||
@ -79,14 +89,15 @@ const addState = connect(
|
||||
function Nav(args) {
|
||||
const {
|
||||
account,
|
||||
sendInstanceState,
|
||||
sendAccountInstances,
|
||||
sendInstanceList,
|
||||
|
||||
ping,
|
||||
team,
|
||||
instances,
|
||||
game,
|
||||
|
||||
sendInstanceState,
|
||||
sendAccountInstances,
|
||||
sendInstanceList,
|
||||
|
||||
setTestGame,
|
||||
setTestInstance,
|
||||
setNav,
|
||||
@ -122,8 +133,18 @@ function Nav(args) {
|
||||
|
||||
const canJoin = team.some(c => !c);
|
||||
|
||||
const accountStatus = account
|
||||
? (<div className="header-status">
|
||||
<h2 className="header-username">{account.name}</h2>
|
||||
{saw(pingColour(ping))}
|
||||
<div className="ping-text">{ping}ms</div>
|
||||
</div>)
|
||||
: false;
|
||||
|
||||
return (
|
||||
<nav onClick={hideNav} >
|
||||
<h1 className="header-title">mnml.gg</h1>
|
||||
{accountStatus}
|
||||
<button onClick={() => navTo('team')}>1. Select Team</button>
|
||||
<button disabled={canJoin} onClick={() => navTo('list')}>2. Join</button>
|
||||
<hr />
|
||||
|
||||
56
client/src/components/team.footer.jsx
Normal file
56
client/src/components/team.footer.jsx
Normal file
@ -0,0 +1,56 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('./../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { team, showNav } = state;
|
||||
|
||||
return {
|
||||
team,
|
||||
showNav,
|
||||
};
|
||||
},
|
||||
function receiveDispatch(dispatch) {
|
||||
function navToList() {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
return dispatch(actions.setNav('list'));
|
||||
}
|
||||
|
||||
function setShowNav(v) {
|
||||
return dispatch(actions.setShowNav(v));
|
||||
}
|
||||
|
||||
return {
|
||||
navToList,
|
||||
setShowNav,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function TeamFooter(args) {
|
||||
const {
|
||||
showNav,
|
||||
team,
|
||||
navToList,
|
||||
setShowNav,
|
||||
} = args;
|
||||
|
||||
if (!team) return false;
|
||||
|
||||
return (
|
||||
<footer>
|
||||
<button id="nav-btn" onClick={() => setShowNav(!showNav)} >☰</button>
|
||||
<button
|
||||
disabled={team.some(c => !c)}
|
||||
className="instance-btn instance-ui-btn right"
|
||||
onClick={() => navToList()}>
|
||||
Join Instance
|
||||
</button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(TeamFooter);
|
||||
@ -12,14 +12,13 @@ const idSort = stringSort('id');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, constructs, team, account } = state;
|
||||
const { ws, constructs, team } = state;
|
||||
|
||||
function sendConstructSpawn(name) {
|
||||
return ws.sendConstructSpawn(name);
|
||||
}
|
||||
|
||||
return {
|
||||
account,
|
||||
constructs,
|
||||
team,
|
||||
sendConstructSpawn,
|
||||
@ -31,29 +30,19 @@ const addState = connect(
|
||||
dispatch(actions.setTeam(constructIds));
|
||||
}
|
||||
|
||||
function navToList() {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
return dispatch(actions.setNav('list'));
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
setTeam,
|
||||
navToList,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function Team(args) {
|
||||
const {
|
||||
account,
|
||||
constructs,
|
||||
team,
|
||||
|
||||
setTeam,
|
||||
sendConstructSpawn,
|
||||
navToList,
|
||||
} = args;
|
||||
|
||||
if (!constructs) return <div></div>;
|
||||
@ -98,25 +87,10 @@ function Team(args) {
|
||||
const spawnButtons = range(spawnButtonsNum)
|
||||
.map(i => <SpawnButton key={constructs.length + i} spawn={name => sendConstructSpawn(name)} />);
|
||||
|
||||
|
||||
const header = (
|
||||
<div className="top">
|
||||
<button
|
||||
disabled={team.some(c => !c)}
|
||||
className="instance-btn instance-ui-btn right"
|
||||
onClick={() => navToList()}>
|
||||
Join Instance
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<main className="menu-constructs">
|
||||
{header}
|
||||
<div className="constructs-list">
|
||||
<main className="team">
|
||||
{constructPanels}
|
||||
{spawnButtons}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ function errorToast(err) {
|
||||
return toast.error({
|
||||
title: 'BEEP BOOP',
|
||||
message: err,
|
||||
position: 'bottomCenter',
|
||||
position: 'topRight',
|
||||
});
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ function createSocket(events) {
|
||||
ws.addEventListener('open', () => {
|
||||
toast.info({
|
||||
message: 'connected',
|
||||
position: 'bottomCenter',
|
||||
position: 'topRight',
|
||||
});
|
||||
|
||||
sendPing();
|
||||
@ -303,7 +303,7 @@ function createSocket(events) {
|
||||
console.error('WebSocket closed', event);
|
||||
toast.warning({
|
||||
message: 'disconnected',
|
||||
position: 'bottomCenter',
|
||||
position: 'topRight',
|
||||
});
|
||||
return setTimeout(connect, 5000);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user