diff --git a/VERSION b/VERSION index 3e1ad720..8e03717d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.0 \ No newline at end of file +1.5.1 \ No newline at end of file diff --git a/WORKLOG.md b/WORKLOG.md index f4230f25..8f93a003 100644 --- a/WORKLOG.md +++ b/WORKLOG.md @@ -1,65 +1,56 @@ # WORK WORK -## NOW -*PRODUCTION* -* ACP - * essential - * serde serialize privatise - * mobile styles - * can't reset password without knowing password =\ +## NOW (Before PAX) - * treats - * client animation bpm - * background colour changes depending on time of day - * susbcriber gold name in instance +*PRODUCTION* + +* mobile styles +* mobile info page + +* Add TOS and accept to register page + +* can't reset password without knowing password =\ + +## SOON (Before or After PAX) * bot game grind - -* msg pane - +* ACP + * essential + * serde serialize privatise +* msg pane / chatwheel * audio - -## SOON -*SERVER* -* modules - * troll life -> dmg - * prince of peace - * bonus healing / no damage - * fuck magic - * empower on ko + * treats + * susbcriber gold name in instance + * client animation bpm + * background colour changes depending on time of day * rework vecs into sets * remove names so games/instances are copy *$$$* -* chatwheel -* eth adapter -* illusions -* vaporwave -* crop circles -* insects -* sacred geometry -* skulls / day of the dead -* Aztec -* youkai -* Industrial + * chatwheel + * eth adapter + * illusions + * vaporwave + * crop circles + * insects + * sacred geometry + * skulls / day of the dead + * Aztec + * youkai + * Industrial *CLIENT* -fix info highlighting -theme toasts -mobile info page -reconnect based on time delta -consolidate game and instance + theme toasts -*SERVER* -* vbox drops chances - * 50% spec, 25% colour etc + reconnect based on time delta + consolidate game and instance -* mnml tv + * elo + leaderboards + + * mnml tv ## LATER -* elo + leaderboards * constants -* change to ownership pattern $$$ * Items @@ -69,6 +60,13 @@ $$$ * Highlight (dota) colour * fx colours + styles +* modules + * troll life -> dmg + * prince of peace + * bonus healing / no damage + * fuck magic + * empower on ko + # Mechanics * 10d chaos maths, not rock paper scissors * phys is faster and chaotic diff --git a/acp/acp.js b/acp/acp.js index 0f4b8299..03ee6846 100644 --- a/acp/acp.js +++ b/acp/acp.js @@ -12,7 +12,7 @@ require('./../client/assets/styles/instance.less'); require('./../client/assets/styles/vbox.less'); require('./../client/assets/styles/game.less'); require('./../client/assets/styles/styles.mobile.css'); -require('./../client/assets/styles/instance.mobile.css'); +require('./../client/assets/styles/instance.mobile.less'); // kick it off require('./src/acp'); diff --git a/acp/package.json b/acp/package.json index 3d3a55d5..de966aac 100644 --- a/acp/package.json +++ b/acp/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.5.0", + "version": "1.5.1", "description": "", "main": "index.js", "scripts": { diff --git a/bin/client.sh b/bin/client.sh index 922b77d3..2ae62d06 100755 --- a/bin/client.sh +++ b/bin/client.sh @@ -13,9 +13,9 @@ rm -rf dist npm i npm run build -echo "Building acp version $VERSION" -cd $MNML_PATH/acp -rm -rf dist -npm i -npm run build -mv dist/* $MNML_PATH/client/dist/ +# echo "Building acp version $VERSION" +# cd $MNML_PATH/acp +# rm -rf dist +# npm i +# npm run build +# mv dist/* $MNML_PATH/client/dist/ diff --git a/client/assets/styles/footer.less b/client/assets/styles/footer.less index 8ab8873a..cf9b6012 100644 --- a/client/assets/styles/footer.less +++ b/client/assets/styles/footer.less @@ -6,6 +6,7 @@ footer { button { margin: 0; + border-radius: 0; border: none; background: #222; font-size: 1.5em; diff --git a/client/assets/styles/game.less b/client/assets/styles/game.less index 0a71051c..a8765ba5 100644 --- a/client/assets/styles/game.less +++ b/client/assets/styles/game.less @@ -317,37 +317,58 @@ grid-template-rows: 1fr 0.2fr 1.5fr; grid-template-columns: 1fr; - } - .game .stats div { - padding: 0; - } + .game-construct { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: min-content 1fr; - .game .stats .max { - display: none; - } + .left { + grid-template-rows: min-content min-content; + } - .game .stats .value { - display: flex; - } + .skills { + button { + padding: 0 0.5em ; + margin: 0; + } + } - .game .stats svg { - height: 1em; - } + .stats div { + padding: 0; + } - .game .stats div { - margin: 0 0.2em; - } + .stats .max { + display: none; + } - .game .effects { - font-size: 100%; - } + .stats .value { + display: flex; + } - #mnml .game .skills button, #mnml .game .stats { - font-size: 75%; - } + .stats svg { + height: 1em; + } - .game-construct .name { - display: none; + .stats div { + margin: 0 0.2em; + } + + .effects { + font-size: 100%; + } + + .skills button, .stats, .name { + font-size: 75%; + } + } + + .opponent { + .game-construct { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: min-content 1fr; + } + } } } \ No newline at end of file diff --git a/client/assets/styles/instance.mobile.css b/client/assets/styles/instance.mobile.less similarity index 77% rename from client/assets/styles/instance.mobile.css rename to client/assets/styles/instance.mobile.less index 52eceb82..07c76286 100644 --- a/client/assets/styles/instance.mobile.css +++ b/client/assets/styles/instance.mobile.less @@ -1,3 +1,5 @@ +@import 'colours.less'; + @media (max-width: 800px) { .instance { font-size: 8pt; @@ -7,25 +9,29 @@ grid-template-areas: "vbox" "constructs"; + + .info { + display: none; + } } .instance .nav-btn { display: initial; } - /* Default view */ - .instance .equip { display: none; } - .instance .info { display: none; } - .instance .construct-list { display: none; } .vbox { grid-area: vbox; + margin-bottom: 0; display: grid; - grid-template-rows: min-content min-content min-content min-content min-content; + grid-template-rows: min-content min-content min-content min-content; grid-template-columns: 1fr; grid-template-areas: "vbox" "varrow" "inventory" - "carrow" "combiner"; + + &:not(.visible) { + display: none; + } } .vbox-arrow { @@ -44,27 +50,13 @@ margin: 0; } - /* constructs toggled on */ - .instance.constructs-visible .vbox { - display: none; - } + .construct-list { + display: grid; + grid-auto-rows: 1fr; - .instance.constructs-visible .equip { - display: initial; - grid-area: vbox; - margin: 0; - } - - .instance.constructs-visible .highlight { - display: initial; - } - - .instance.constructs-visible .construct-list { - display: flex; - flex-flow: row; - align-content: flex-end; - height: 100%; - margin: 0; + .instance-construct:not(.visible) { + display: none; + }; } .vbox-inventory { @@ -87,7 +79,6 @@ } .instance-construct { - flex: 1; display: grid; grid-template-rows: min-content min-content min-content 1fr min-content; grid-template-areas: @@ -106,10 +97,6 @@ transition-timing-function: ease; } - .instance-construct .avatar { - min-height: 150px; - } - .instance-construct:first-child { border-left-width: 0; } diff --git a/client/assets/styles/styles.less b/client/assets/styles/styles.less index c512bf0f..2a1d8451 100644 --- a/client/assets/styles/styles.less +++ b/client/assets/styles/styles.less @@ -1,6 +1,6 @@ @import 'colours.less'; -html, body, #mnml { +html body { margin: 0; background-color: black; @@ -12,7 +12,9 @@ html, body, #mnml { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; +} +#mnml { /* this is the sweet nectar to keep it full page*/ height: 100vh; max-height: 100vh; @@ -21,7 +23,7 @@ html, body, #mnml { /* stops inspector going skitz*/ overflow-x: hidden; - overflow-y: hidden; + // overflow-y: hidden; } @media (min-width: 1921px) { diff --git a/client/assets/styles/styles.mobile.css b/client/assets/styles/styles.mobile.css index 6b09a6c7..ec43c8d2 100644 --- a/client/assets/styles/styles.mobile.css +++ b/client/assets/styles/styles.mobile.css @@ -1,12 +1,16 @@ @media (max-width: 800px) { #mnml { - font-size: 14pt; - padding: 1em 0 0 0; + font-size: 12pt; + padding: 0; grid-template-columns: 1fr; grid-template-rows: 1fr min-content; grid-template-areas: "main" "footer"; + + height: 100vh; + max-height: initial; + min-height: initial; } #mnml button { @@ -50,6 +54,8 @@ */ main { overflow-x: hidden; + overflow-y: initial; + max-height: 100vh; padding: 0 0.5em; } diff --git a/client/index.js b/client/index.js index ae5df689..8ad272c9 100644 --- a/client/index.js +++ b/client/index.js @@ -9,7 +9,7 @@ require('./assets/styles/vbox.less'); require('./assets/styles/game.less'); require('./assets/styles/player.less'); require('./assets/styles/styles.mobile.css'); -require('./assets/styles/instance.mobile.css'); +require('./assets/styles/instance.mobile.less'); // kick it off require('./src/app'); diff --git a/client/package.json b/client/package.json index 51074c78..bdfacdc3 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.5.0", + "version": "1.5.1", "description": "", "main": "index.js", "scripts": { @@ -19,6 +19,7 @@ "async": "^2.6.2", "borc": "^2.0.3", "docco": "^0.7.0", + "hammerjs": "^2.0.8", "izitoast": "^1.4.0", "keymaster": "^1.6.2", "linkstate": "^1.1.1", diff --git a/client/src/actions.jsx b/client/src/actions.jsx index ccfadcaa..282d2474 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -27,6 +27,7 @@ export const setItemInfo = value => ({ type: 'SET_ITEM_INFO', value }); export const setItemUnequip = value => ({ type: 'SET_ITEM_UNEQUIP', value }); export const setMtxActive = value => ({ type: 'SET_MTX_ACTIVE', value }); export const setNav = value => ({ type: 'SET_NAV', value }); +export const setNavInstance = value => ({ type: 'SET_NAV_INSTANCE', value }); export const setPing = value => ({ type: 'SET_PING', value }); export const setPlayer = value => ({ type: 'SET_PLAYER', value }); export const setReclaiming = value => ({ type: 'SET_RECLAIMING', value }); diff --git a/client/src/components/footer.jsx b/client/src/components/footer.jsx index edad7dd2..07b3caa3 100644 --- a/client/src/components/footer.jsx +++ b/client/src/components/footer.jsx @@ -5,7 +5,7 @@ const { connect } = require('preact-redux'); const actions = require('./../actions'); const TeamFooter = require('./team.footer'); -const ListFooter = require('./list.footer'); +const PlayFooter = require('./play.footer'); const InstanceFooter = require('./instance.footer'); const GameFooter = require('./game.footer'); @@ -30,8 +30,8 @@ function renderHeader(args) { if (game) return ; if (instance) return ; - if (nav === 'team') return ; - if (nav === 'list') return ; + if (nav === 'team' || nav === 'account') return ; + if (nav === 'play' || nav === 'shop' || !nav) return ; } diff --git a/client/src/components/game.footer.jsx b/client/src/components/game.footer.jsx index 1daa4981..40095d45 100644 --- a/client/src/components/game.footer.jsx +++ b/client/src/components/game.footer.jsx @@ -9,7 +9,7 @@ const addState = connect( ws, game, account, - showNav, + animating, } = state; function sendGameReady() { @@ -24,9 +24,9 @@ const addState = connect( return { game, account, + animating, sendInstanceState, sendGameReady, - showNav, }; }, @@ -36,15 +36,7 @@ const addState = connect( dispatch(actions.setInstance(null)); } - function skip() { - dispatch(actions.setSkip(true)); - } - - function setShowNav(v) { - return dispatch(actions.setShowNav(v)); - } - - return { setShowNav, quit, skip }; + return { quit }; } ); @@ -53,22 +45,13 @@ function GameFooter(props) { const { game, account, - showNav, + animating, quit, - setShowNav, sendGameReady, sendInstanceState, } = props; - if (!game) { - return ( -
- -
- ); - } - const playerTeam = game.players.find(t => t.id === account.id); function quitClick() { @@ -86,6 +69,7 @@ function GameFooter(props) { const readyBtn = ( {game.phase === 'Finish' && quitBtn } {game.phase === 'Skill' && readyBtn } diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx index 12f78532..0da7dced 100644 --- a/client/src/components/instance.component.jsx +++ b/client/src/components/instance.component.jsx @@ -1,6 +1,9 @@ +const { Component } = require('preact'); const preact = require('preact'); const { connect } = require('preact-redux'); +const Hammer = require('hammerjs'); + const Vbox = require('./vbox.component'); const InfoContainer = require('./info.container'); const InstanceConstructsContainer = require('./instance.constructs'); @@ -11,8 +14,14 @@ const actions = require('../actions'); const addState = connect( function receiveState(state) { - const { instance, nav } = state; - return { instance, nav }; + const { instance, + nav, + navInstance, + } = state; + return { instance, + nav, + navInstance, + }; }, function receiveDispatch(dispatch) { @@ -20,6 +29,11 @@ const addState = connect( return dispatch(actions.setInfo(c)); } + function setNavInstance(c) { + return dispatch(actions.setNavInstance(c)); + } + + function clearItems() { dispatch(actions.setCombiner([])); dispatch(actions.setReclaiming(false)); @@ -33,38 +47,72 @@ const addState = connect( return { setInfo, clearItems, + setNavInstance, }; } ); -function Instance(args) { - const { - instance, - setInfo, - clearItems, +class Instance extends Component { + render(args) { + const { + instance, + setInfo, + clearItems, + } = args; - nav, - } = args; + if (!instance) return false; - if (!instance) return false; + if (instance.phase !== 'InProgress') { + return ; + } - if (instance.phase !== 'InProgress') { - return ; + function instanceClick(e) { + e.stopPropagation(); + clearItems(); + } + + function onTouchMove(e) { + e.preventDefault(); + } + + return ( +
setInfo(null)} onTouchMove={onTouchMove}> + + + +
+ ); } - function instanceClick(e) { - e.stopPropagation(); - clearItems(); + componentDidMount() { + this.bindSwipes(); } - const instanceClasses = `instance ${nav === 'constructs' ? 'constructs-visible' : ''}`; - return ( -
setInfo(null)} > - - - -
- ); + bindSwipes() { + const instance = document.getElementById('instance'); + if (!instance) return setTimeout(this.bindSwipes, 50); + if (this.h) this.h.destroy(); + this.h = new Hammer(instance); + const display = ['vbox', 'c0', 'c1', 'c2']; + + this.h.on('swiperight', () => { + const { + navInstance, + setNavInstance, + } = this.props; + setNavInstance(navInstance === 0 ? 3 : navInstance - 1); + }); + + this.h.on('swipeleft', () => { + const { + navInstance, + setNavInstance, + } = this.props; + setNavInstance((navInstance + 1) % 4); + }); + + return true; + } } module.exports = addState(Instance); diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index 9afd9cc5..fce829f5 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -9,7 +9,16 @@ const actions = require('../actions'); const addState = connect( function receiveState(state) { - const { ws, instance, player, account, itemInfo, itemEquip, activeConstruct } = state; + const { + ws, + instance, + player, + account, + itemInfo, + itemEquip, + activeConstruct, + navInstance, + } = state; function sendVboxApply(constructId, i) { return ws.sendVboxApply(instance.id, constructId, i); @@ -26,6 +35,7 @@ const addState = connect( sendVboxApply, itemInfo, itemEquip, + navInstance, activeConstruct, sendUnequip, }; @@ -63,7 +73,6 @@ const addState = connect( function Construct(props) { const { - activeConstruct, itemEquip, construct, player, @@ -74,6 +83,7 @@ function Construct(props) { itemInfo, setInfo, sendUnequip, + mobileVisible, } = props; function onClick(e) { @@ -191,8 +201,10 @@ function Construct(props) { ; }); + const classes = `instance-construct ${mobileVisible ? 'visible' : ''}`; + return ( -
+

{construct.name}

hoverInfo(e, 'constructSkills')} > @@ -224,6 +236,7 @@ function InstanceConstructs(props) { setItemUnequip, setItemEquip, sendUnequip, + navInstance, } = props; if (!player) return false; @@ -242,6 +255,7 @@ function InstanceConstructs(props) { itemInfo, setVboxHighlight, sendUnequip, + mobileVisible: navInstance === i + 1, })); const classes = `construct-list`; diff --git a/client/src/components/instance.footer.jsx b/client/src/components/instance.footer.jsx index ee8cf2c3..82e01681 100644 --- a/client/src/components/instance.footer.jsx +++ b/client/src/components/instance.footer.jsx @@ -5,32 +5,22 @@ const actions = require('../actions'); const addState = connect( function receiveState(state) { - const { ws, instance, player, nav, showNav } = state; + const { ws, instance, player, nav } = state; function sendInstanceReady() { return ws.sendInstanceReady(instance.id); } - return { player, instance, sendInstanceReady, nav, showNav }; + return { player, instance, sendInstanceReady, nav }; }, 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, }; } ); @@ -39,30 +29,11 @@ function Instance(args) { const { instance, player, - nav, - showNav, - - setInfo, - setNav, - setShowNav, sendInstanceReady, } = args; - if (!instance || !player) { - return ( -
- -
- ); - } - - function hoverInfo(e, info) { - e.stopPropagation(); - return setInfo(info); - } - - const rdyClasses = `${player.ready ? 'ready ready-btn' : 'ready-btn'}`; + const rdyClasses = `ready-btn ready`; const readyInfo = instance.phase === 'Lobby' ? 'lobbyReady' : 'ready'; @@ -70,27 +41,11 @@ function Instance(args) { const readyBtn = ( ); - function navClick() { - if (nav === 'vbox') return setNav('constructs'); - return setNav('vbox'); - } - - const navBtn = instance.phase === 'InProgress' - ? ( - - ) - : null; - const zero = Date.parse(instance.phase_start); const now = Date.now(); const end = Date.parse(instance.phase_end); @@ -118,8 +73,6 @@ function Instance(args) { return (
{timer} - - {navBtn} {readyBtn}
); diff --git a/client/src/components/list.footer.jsx b/client/src/components/list.footer.jsx deleted file mode 100644 index 65109d72..00000000 --- a/client/src/components/list.footer.jsx +++ /dev/null @@ -1,48 +0,0 @@ -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) { - return false; - - // const { - // showNav, - - // navToTeam, - // setShowNav, - // } = args; - - // return ( - //
- // - // - //
- // ); -} - -module.exports = addState(ListFooter); diff --git a/client/src/components/play.footer.jsx b/client/src/components/play.footer.jsx new file mode 100644 index 00000000..f8a8479a --- /dev/null +++ b/client/src/components/play.footer.jsx @@ -0,0 +1,139 @@ +const preact = require('preact'); +const { connect } = require('preact-redux'); + +const { errorToast, infoToast } = require('../utils'); + +const AccountBox = require('./account.box'); + +const addState = connect( + function receiveState(state) { + const { + ws, + instances, + invite, + } = state; + + function sendInstanceState(id) { + ws.sendInstanceState(id); + } + + function sendInstancePractice() { + ws.sendInstancePractice(); + } + + function sendInstanceQueue() { + ws.sendInstanceQueue(); + } + + function sendInstanceInvite() { + ws.sendInstanceInvite(); + } + + return { + instances, + invite, + + sendInstanceState, + sendInstanceQueue, + sendInstancePractice, + sendInstanceInvite, + }; + } +); + +function JoinButtons(args) { + const { + instances, + invite, + + sendInstanceState, + sendInstanceQueue, + sendInstancePractice, + sendInstanceInvite, + } = args; + + const discordBtn = ( + + ); + + if (instances.length) { + return ( +
+
+ +
+ ); + } + + const inviteBtn = () => { + if (!invite) { + return ( + + ); + } + + function copyClick(e) { + const link = `${document.location.origin}#join=${invite}`; + const textArea = document.createElement('textarea', { id: '#clipboard' }); + textArea.value = link; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + infoToast('Invite link copied.'); + } catch (err) { + console.error('link copy error', err); + errorToast('Invite link copy error.'); + } + + document.body.removeChild(textArea); + return true; + } + + return ( + + ); + }; + + return ( +
+
+ + {inviteBtn()} + +
+ ); +} + +module.exports = addState(JoinButtons); diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index e659ee72..53c03819 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -17,6 +17,7 @@ const addState = connect( vboxSelected, itemInfo, itemUnequip, + navInstance, } = state; function sendVboxDiscard() { @@ -51,7 +52,8 @@ const addState = connect( vboxSelected, itemInfo, itemUnequip, - sendItemUnequip + sendItemUnequip, + navInstance, }; }, @@ -90,6 +92,7 @@ const addState = connect( function Vbox(args) { const { combiner, + navInstance, // instance, itemInfo, player, @@ -348,7 +351,7 @@ function Vbox(args) { return setInfo(info); } - const classes = 'vbox'; + const classes = `vbox ${navInstance === 0 ? 'visible' : ''}`; return (
{vboxElement()} diff --git a/client/src/components/welcome.about.jsx b/client/src/components/welcome.about.jsx deleted file mode 100644 index 0f33b942..00000000 --- a/client/src/components/welcome.about.jsx +++ /dev/null @@ -1,69 +0,0 @@ -// eslint-disable-next-line -const preact = require('preact'); -const { Component } = require('preact') -const { connect } = require('preact-redux'); -const linkState = require('linkstate').default; - -const { postData, errorToast, infoToast } = require('../utils'); - -const addState = connect( - (state) => { - const { - ws - } = state; - - function submitRegister(name, password, code) { - postData('/account/register', { name, password, code }) - .then(res => res.json()) - .then(data => { - if (data.error) return errorToast(data.error); - infoToast(data.message); - ws.connect(); - }) - .catch(error => errorToast(error)); - } - - return { - submitRegister, - } - }, -); - -function Register(args) { - const { - submitRegister, - navRegister, - } = args; - - return ( - - ); -} - -module.exports = addState(Register); diff --git a/client/src/components/welcome.jsx b/client/src/components/welcome.jsx index 70bde16d..6146b7a0 100644 --- a/client/src/components/welcome.jsx +++ b/client/src/components/welcome.jsx @@ -19,7 +19,7 @@ function Welcome() { }; return ( -
+