mnml/client/src/components/vbox.component.jsx
2019-05-22 12:07:16 +10:00

339 lines
9.5 KiB
JavaScript

const preact = require('preact');
const range = require('lodash/range');
const { connect } = require('preact-redux');
const shapes = require('./shapes');
const { convertItem } = require('./../utils');
const actions = require('../actions');
const addState = connect(
function receiveState(state) {
const {
ws,
account,
instance,
combiner,
reclaiming,
vboxHighlight,
itemInfo,
} = state;
const player = instance.players.find(p => p.id === account.id);
function sendVboxDiscard() {
return ws.sendVboxDiscard(instance.id);
}
function sendVboxAccept(group, index) {
return ws.sendVboxAccept(instance.id, group, index);
}
function sendVboxCombine() {
return ws.sendVboxCombine(instance.id, combiner);
}
function sendVboxReclaim(i) {
return ws.sendVboxReclaim(instance.id, i);
}
return {
combiner,
instance,
player,
reclaiming,
sendVboxAccept,
sendVboxCombine,
sendVboxDiscard,
sendVboxReclaim,
vboxHighlight,
itemInfo,
};
},
function receiveDispatch(dispatch) {
function setCombiner(c) {
return dispatch(actions.setCombiner(c));
}
function setReclaiming(v) {
return dispatch(actions.setReclaiming(v));
}
function setInfo(item) {
return dispatch(actions.setInfo(item));
}
function setVboxHighlight(v) {
return dispatch(actions.setVboxHighlight(v));
}
return {
setCombiner,
setReclaiming,
setInfo,
setVboxHighlight,
};
}
);
function Vbox(args) {
const {
combiner,
instance,
itemInfo,
player,
reclaiming,
sendVboxAccept,
sendVboxCombine,
sendVboxDiscard,
sendVboxReclaim,
vboxHighlight,
setCombiner,
setInfo,
setReclaiming,
setVboxHighlight,
} = args;
if (!player) return false;
if (instance.phase === 'Lobby') return false;
const { vbox } = player;
// function setHighlight(type) {
// if (type === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.item));
// if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.item));
// return false;
// }
function combinerChange(newCombiner) {
setCombiner(newCombiner);
if (newCombiner.every(c => c === null)) return setVboxHighlight([]);
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
const filteredCombos = itemInfo.combos
.filter(combo => combinerValues.every(u => combo.units.includes(u)));
const comboValues = itemInfo.items.filter(v => {
if (!filteredCombos.some(c => c.units.includes(v.item))) return false;
if (!['Red', 'Green', 'Blue'].includes(v.item) && combinerValues.includes(v.item)) return false;
return true;
});
return setVboxHighlight(comboValues.map(v => v.item));
}
//
// VBOX
//
const free = [];
for (let i = 0; i < 6; i++) {
free.push([vbox.free[0][i], vbox.free[1][i], vbox.free[2][i]]);
}
let vboxTimer;
const LONG_TOUCH_TIME = 500;
function vboxTouchStart(e, i, j) {
vboxTimer = (setTimeout(() => {
sendVboxAccept(j, i);
vboxTimer = null;
}, LONG_TOUCH_TIME));
return true;
}
function vboxTouchEnd(e, i, j) {
if (vboxTimer) {
clearTimeout(vboxTimer);
}
return true;
}
function vboxTouchMove(e) {
if (vboxTimer) clearTimeout(vboxTimer);
e.stopPropagation();
return true;
}
function vboxHover(e, v) {
if (v) {
setInfo(v);
e.stopPropagation();
}
return true;
}
const freeRows = free.map((row, i) => {
const cells = row.map((c, j) => {
const highlighted = c && vboxHighlight.includes(c);
return <td
key={j}
className={`${highlighted ? 'highlight' : ''}`}
onTouchStart={e => vboxTouchStart(e, i, j)}
onTouchEnd={e => vboxTouchEnd(e, i, j)}
onTouchMove={e => vboxTouchMove(e)}
// onClick={freeClick}
onDblClick={() => sendVboxAccept(j, i) }
onMouseOver={e => vboxHover(e, c)}
>
{convertItem(c)}
</td>;
});
return (
<tr key={i}>
{cells}
</tr>
);
});
//
// INVENTORY
//
function boundClick(e, i) {
const value = vbox.bound[i];
if (reclaiming && value) return sendVboxReclaim(i);
if (value) {
const insert = combiner.findIndex(j => j === null);
if (insert === -1) return combinerChange([i, null, null]);
combiner[insert] = i;
return combinerChange(combiner);
}
return false;
}
const boundTds = range(0, 9).map(i => {
const value = vbox.bound[i];
if (combiner.indexOf(i) > -1) {
return (
<td
key={i}>
&nbsp;
</td>
);
}
const highlighted = value && vboxHighlight.includes(value);
return (
<td
key={i}
className={`${highlighted ? 'highlight' : ''}`}
onMouseOver={(e) => vboxHover(e, value)}
onClick={e => boundClick(e, i, highlighted) }>
{convertItem(value)}
</td>
);
});
const boundRows = [
<tr key={0} >
{boundTds[0]}
{boundTds[1]}
{boundTds[2]}
</tr>,
<tr key={1}>
{boundTds[3]}
{boundTds[4]}
{boundTds[5]}
</tr>,
<tr key={2}>
{boundTds[6]}
{boundTds[7]}
{boundTds[8]}
</tr>,
];
//
// COMBINER
//
function combinerRmv(i) {
combiner[i] = null;
return combinerChange(combiner);
}
const combinerElement = (
<table className="vbox-table">
<tbody>
<tr>
<td onClick={() => combinerRmv(0)}>
{combiner[0] !== null ? convertItem(vbox.bound[combiner[0]]) : shapes.vboxColour('gray')}
</td>
<td onClick={() => combinerRmv(1)}>
{combiner[1] !== null ? convertItem(vbox.bound[combiner[1]]) : shapes.vboxColour('gray')}
</td>
<td onClick={() => combinerRmv(2)}>
{convertItem(vbox.bound[combiner[2]])}
</td>
</tr>
</tbody>
</table>
);
//
// EVERYTHING
//
function reclaimClick(e) {
e.stopPropagation();
return setReclaiming(!reclaiming);
}
function hoverInfo(e, info) {
e.stopPropagation();
return setInfo(info);
}
const classes = `vbox`;
const reclaimClass = `instance-btn instance-ui-btn vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;
return (
<div className={classes}>
<div className='vbox-box' onClick={() => setReclaiming(false)} onMouseOver={e => hoverInfo(e, 'vbox')} >
<div className="vbox-hdr">
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>VBOX</h3>
<div className="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
</div>
<button
className="instance-btn instance-ui-btn vbox-btn"
onMouseOver={e => hoverInfo(e, 'reroll')}
onClick={() => sendVboxDiscard()}>
Reroll
</button>
<table className="vbox-table">
<tbody>
{freeRows}
</tbody>
</table>
</div>
<div className='vbox-inventory' onClick={() => setReclaiming(false)} onMouseOver={e => hoverInfo(e, 'inventory')} >
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>INVENTORY</h3>
<button
className={reclaimClass}
onMouseOver={e => hoverInfo(e, 'reclaim')}
onClick={reclaimClick}>
reclaim
</button>
<table className="vbox-table">
<tbody>
{boundRows}
</tbody>
</table>
</div>
<div className="vbox-combiner" onMouseOver={e => hoverInfo(e, 'combiner')} >
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>I-COMBINATOR</h3>
<button
className="instance-btn instance-ui-btn vbox-btn"
onMouseOver={e => hoverInfo(e, 'refine')}
onClick={() => sendVboxCombine()}>
refine
</button>
{combinerElement}
</div>
</div>
);
}
module.exports = addState(Vbox);