pog
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
export const SET_ACCOUNT = 'SET_ACCOUNT';
|
||||
export const setAccount = value => ({ type: SET_ACCOUNT, value });
|
||||
|
||||
export const SET_CRYPS = 'SET_CRYPS';
|
||||
export const setCryps = value => ({ type: SET_CRYPS, value });
|
||||
|
||||
export const SET_INSTANCES = 'SET_INSTANCES';
|
||||
export const setInstances = value => ({ type: SET_INSTANCES, value });
|
||||
|
||||
export const SET_INSTANCE = 'SET_INSTANCE';
|
||||
export const setInstance = value => ({ type: SET_INSTANCE, value });
|
||||
|
||||
export const SET_GAME = 'SET_GAME';
|
||||
export const setGame = value => ({ type: SET_GAME, value });
|
||||
|
||||
export const SET_ACTIVE_ITEM = 'SET_ACTIVE_ITEM';
|
||||
export const setActiveItem = value => ({ type: SET_ACTIVE_ITEM, value });
|
||||
|
||||
export const SET_ACTIVE_INCOMING = 'SET_ACTIVE_INCOMING';
|
||||
export const setActiveIncoming = value => ({ type: SET_ACTIVE_INCOMING, value });
|
||||
|
||||
export const SET_ACTIVE_SKILL = 'SET_ACTIVE_SKILL';
|
||||
export const setActiveSkill = (crypId, skill) => ({ type: SET_ACTIVE_SKILL, value: crypId ? { crypId, skill } : null });
|
||||
|
||||
export const SET_WS = 'SET_WS';
|
||||
export const setWs = value => ({ type: SET_WS, value });
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
const actions = require('../actions');
|
||||
|
||||
const InstanceListContainer = require('./instance.list.container');
|
||||
const CrypSpawnContainer = require('./cryp.spawn.container');
|
||||
const CrypListContainer = require('./cryp.list.container');
|
||||
const GameContainer = require('./game.container');
|
||||
const InstanceContainer = require('./instance.container');
|
||||
|
||||
const addState = connect(
|
||||
(state) => {
|
||||
const { game, instance, ws } = state;
|
||||
|
||||
if (!game) {
|
||||
console.log('clear gs interval');
|
||||
// ws.clearGameStateInterval();
|
||||
}
|
||||
|
||||
return { game, instance };
|
||||
},
|
||||
(dispatch) => {
|
||||
function setGame(game) {
|
||||
dispatch(actions.setGame(game));
|
||||
}
|
||||
return { setGame };
|
||||
},
|
||||
);
|
||||
|
||||
function renderBody(props) {
|
||||
const { game, instance, setGame } = props;
|
||||
if (game) {
|
||||
return (
|
||||
<div>
|
||||
<GameContainer />
|
||||
<button
|
||||
className="button is-dark is-fullwidth"
|
||||
type="submit"
|
||||
onClick={() => setGame(null)}
|
||||
>
|
||||
Return to Main Menu
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
return (
|
||||
<div>
|
||||
<InstanceContainer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="background"/>
|
||||
<CrypSpawnContainer />
|
||||
<section className="row" >
|
||||
<div className="six columns">
|
||||
<CrypListContainer />
|
||||
</div>
|
||||
<div className="six columns">
|
||||
<InstanceListContainer />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(renderBody);
|
||||
@@ -0,0 +1,27 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const CrypList = require('./cryp.list');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, cryps, activeItem } = state;
|
||||
function sendGamePve(crypId) {
|
||||
return ws.sendGamePve(crypId);
|
||||
}
|
||||
|
||||
function sendGamePvp(crypIds) {
|
||||
return ws.sendGamePvp(crypIds);
|
||||
}
|
||||
|
||||
function sendItemUse(targetId) {
|
||||
if (activeItem) {
|
||||
return ws.sendItemUse(activeItem, targetId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return { cryps, sendGamePve, sendGamePvp, activeItem, sendItemUse };
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = addState(CrypList);
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
const preact = require('preact');
|
||||
|
||||
const { stringSort } = require('./../utils');
|
||||
|
||||
const idSort = stringSort('id');
|
||||
|
||||
function CrypList({ cryps, activeCryp, avatar }) {
|
||||
if (!cryps) return <div>not ready</div>;
|
||||
|
||||
const crypPanels = cryps.sort(idSort).map(cryp => (
|
||||
<div key={cryp.id} className="home-cryp">
|
||||
<h2>{cryp.name}</h2>
|
||||
<div>{cryp.hp.value} HP</div>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={cryp.hp.value === 0}
|
||||
onClick={() => activeCryp(cryp.id)}>
|
||||
activate
|
||||
</button>
|
||||
</div>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
{crypPanels}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = CrypList;
|
||||
@@ -0,0 +1,32 @@
|
||||
const preact = require('preact');
|
||||
|
||||
function renderSpawnButton({ account, sendCrypSpawn }) {
|
||||
let name = '';
|
||||
|
||||
if (!account) return <div>...</div>;
|
||||
|
||||
return false;
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="two columns">
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
placeholder="cryp name"
|
||||
onChange={e => (name = e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="two columns">
|
||||
<button
|
||||
className="button"
|
||||
type="submit"
|
||||
onClick={() => sendCrypSpawn(name)}>
|
||||
Spawn 👾
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = renderSpawnButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const CrypSpawnButton = require('./cryp.spawn.button');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws } = state;
|
||||
function sendCrypSpawn(name) {
|
||||
return ws.sendCrypSpawn(name);
|
||||
}
|
||||
|
||||
return { account: state.account, sendCrypSpawn };
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = addState(CrypSpawnButton);
|
||||
@@ -0,0 +1,48 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const Game = require('./game');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, game, account, activeSkill, activeIncoming } = state;
|
||||
|
||||
function selectSkillTarget(targetTeamId) {
|
||||
if (activeSkill) {
|
||||
return ws.sendGameSkill(game.id, activeSkill.crypId, targetTeamId, activeSkill.skill.skill);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// intercept self casting skills
|
||||
if (activeSkill && activeSkill.skill.self_targeting) {
|
||||
ws.sendGameSkill(game.id, activeSkill.crypId, null, activeSkill.skill.skill);
|
||||
}
|
||||
|
||||
function selectIncomingTarget(crypId) {
|
||||
if (activeIncoming) {
|
||||
return ws.sendGameTarget(game.id, crypId, activeIncoming);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return { game, account, activeSkill, activeIncoming, selectSkillTarget, selectIncomingTarget };
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function setActiveSkill(crypId, skill) {
|
||||
dispatch(actions.setActiveSkill(crypId, skill));
|
||||
}
|
||||
|
||||
function setActiveIncoming(skillId) {
|
||||
dispatch(actions.setActiveIncoming(skillId));
|
||||
}
|
||||
|
||||
|
||||
return { setActiveSkill, setActiveIncoming };
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
module.exports = addState(Game);
|
||||
@@ -0,0 +1,42 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const addState = connect(
|
||||
(state) => {
|
||||
const { ws, cryps } = state;
|
||||
function sendGameJoin(gameId) {
|
||||
return ws.sendGameJoin(gameId, [cryps[0].id]);
|
||||
}
|
||||
|
||||
return { account: state.account, sendGameJoin };
|
||||
},
|
||||
);
|
||||
|
||||
function GameJoinButton({ account, sendGameJoin }) {
|
||||
let gameId = '';
|
||||
|
||||
if (!account) return <div>...</div>;
|
||||
|
||||
return (
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
placeholder="gameId"
|
||||
onChange={e => (gameId = e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<button
|
||||
className="button is-dark is-fullwidth"
|
||||
type="submit"
|
||||
onClick={() => sendGameJoin(gameId)}>
|
||||
Join Game
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(GameJoinButton);
|
||||
Executable
+184
@@ -0,0 +1,184 @@
|
||||
const preact = require('preact');
|
||||
const key = require('keymaster');
|
||||
|
||||
const SKILL_HOT_KEYS = ['Q', 'W', 'E', 'R'];
|
||||
|
||||
function GamePanel(props) {
|
||||
const {
|
||||
game,
|
||||
activeSkill,
|
||||
activeIncoming,
|
||||
setActiveSkill,
|
||||
setActiveIncoming,
|
||||
selectSkillTarget,
|
||||
selectIncomingTarget,
|
||||
account,
|
||||
} = props;
|
||||
|
||||
if (!game) return <div>...</div>;
|
||||
|
||||
const otherTeams = game.teams.filter(t => t.id !== account.id);
|
||||
|
||||
const playerTeam = game.teams.find(t => t.id === account.id);
|
||||
|
||||
const incoming = game.stack.filter(s => s.target_team_id === playerTeam.id).map((inc) => {
|
||||
key.unbind('1');
|
||||
key('1', () => setActiveIncoming(inc.id));
|
||||
return (
|
||||
<div className="tile is-child" key={inc.id}>
|
||||
<div>{JSON.stringify(inc)}</div>
|
||||
<button
|
||||
className="button is-dark is-fullwidth"
|
||||
type="submit"
|
||||
onClick={() => setActiveIncoming(inc.id)}>
|
||||
(1) Block skill: {inc.skill}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
function PlayerCrypCard(cryp) {
|
||||
const skills = cryp.skills.map((skill, i) => {
|
||||
const hotkey = SKILL_HOT_KEYS[i];
|
||||
key.unbind(hotkey);
|
||||
key(hotkey, () => setActiveSkill(cryp.id, skill));
|
||||
|
||||
return (
|
||||
<button
|
||||
key={i}
|
||||
className="button is-dark"
|
||||
type="submit"
|
||||
onClick={() => setActiveSkill(cryp.id, skill)}
|
||||
>
|
||||
({hotkey}) {skill.skill} {skill.cd && `(${skill.cd}T)`}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
const effects = cryp.effects.map((effect, i) => (
|
||||
<div key={i}>{effect} for {effect.turns}T</div>
|
||||
));
|
||||
|
||||
return (
|
||||
<div
|
||||
key={cryp.id}
|
||||
style={ activeIncoming ? { cursor: 'pointer' } : {}}
|
||||
onClick={() => selectIncomingTarget(cryp.id)}
|
||||
className="tile is-vertical">
|
||||
<div className="tile is-child">
|
||||
<div className="columns" >
|
||||
<div className="column is-10">
|
||||
<p className="title">{cryp.name}</p>
|
||||
<p className="subtitle">Level {cryp.lvl}</p>
|
||||
</div>
|
||||
<div className="column">
|
||||
<figure className="image">
|
||||
<svg width="40" height="40" data-jdenticon-value={cryp.name} />
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="has-text-centered">{cryp.hp.value} / {cryp.stam.value} HP </div>
|
||||
<progress className="progress is-dark" value={cryp.hp.value} max={cryp.stam.value}></progress>
|
||||
|
||||
<div className="has-text-centered">{cryp.xp} / {Math.pow(2, cryp.lvl + 1)} XP </div>
|
||||
<progress className="progress is-dark" value={cryp.xp} max={Math.pow(2, cryp.lvl + 1)}></progress>
|
||||
</div>
|
||||
{effects}
|
||||
{skills}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PlayerTeam(team) {
|
||||
const cryps = team.cryps.map(c => PlayerCrypCard(c, setActiveSkill));
|
||||
|
||||
return (
|
||||
<div className="tile">
|
||||
{cryps}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OpponentCrypCard(cryp) {
|
||||
const effects = cryp.effects.map((effect, i) => (
|
||||
<div key={i}>{effect.effect} for {effect.turns}T</div>
|
||||
));
|
||||
|
||||
return (
|
||||
<div key={cryp.id} className="tile is-vertical">
|
||||
<div className="tile is-child">
|
||||
<div className="columns" >
|
||||
<div className="column is-10">
|
||||
<p className="title">{cryp.name}</p>
|
||||
<p className="subtitle">Level {cryp.lvl}</p>
|
||||
</div>
|
||||
<div className="column">
|
||||
<figure className="image">
|
||||
<svg width="40" height="40" data-jdenticon-value={cryp.name} />
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="has-text-centered">{cryp.hp.value} / {cryp.stam.value} HP </div>
|
||||
<progress className="progress is-dark" value={cryp.hp.value} max={cryp.stam.value}></progress>
|
||||
|
||||
<div className="has-text-centered">{cryp.xp} / {Math.pow(2, cryp.lvl + 1)} XP </div>
|
||||
<progress className="progress is-dark" value={cryp.xp} max={Math.pow(2, cryp.lvl + 1)}></progress>
|
||||
|
||||
</div>
|
||||
{effects}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OpponentTeam(team) {
|
||||
const cryps = team.cryps.map(OpponentCrypCard);
|
||||
return (
|
||||
<div
|
||||
className="tile"
|
||||
style={activeSkill ? { cursor: 'pointer' } : {}}
|
||||
onClick={() => selectSkillTarget(team.id)} >
|
||||
{cryps}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// style={{ "min-height": "100%" }}
|
||||
function phaseText(phase) {
|
||||
switch (phase) {
|
||||
case 'Skill':
|
||||
return 'Choose abilities';
|
||||
case 'Target':
|
||||
return 'Block abilities';
|
||||
case 'Finish':
|
||||
return 'Game over';
|
||||
}
|
||||
}
|
||||
|
||||
const logs = game.log.reverse().map((l, i) => (<div key={i}>{l}</div>));
|
||||
|
||||
return (
|
||||
<section className="columns">
|
||||
<div className="column is-2 title is-1">
|
||||
{phaseText(game.phase)}
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
{PlayerTeam(playerTeam, setActiveSkill)}
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<div>
|
||||
{otherTeams.map(OpponentTeam)}
|
||||
</div>
|
||||
<div>
|
||||
{incoming}
|
||||
</div>
|
||||
</div>
|
||||
<div className="column is-2">
|
||||
<div className="title is-4">{logs}</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = GamePanel;
|
||||
@@ -0,0 +1,17 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
|
||||
const LoginContainer = require('./login.container');
|
||||
|
||||
function renderHeader() {
|
||||
return (
|
||||
<header className="row header">
|
||||
<h1 className="cryps-title six columns">
|
||||
cryps.gg
|
||||
</h1>
|
||||
<LoginContainer />
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = renderHeader;
|
||||
@@ -0,0 +1,78 @@
|
||||
const preact = require('preact');
|
||||
const key = require('keymaster');
|
||||
|
||||
function convertVar(v) {
|
||||
return v || '';
|
||||
}
|
||||
|
||||
function Vbox(vbox) {
|
||||
if (!vbox) return false;
|
||||
|
||||
const free = [];
|
||||
for (let i = 0 ; i < vbox.free[0].length; i++) {
|
||||
free.push([vbox.free[0][i], vbox.free[1][i], vbox.free[2][i]]);
|
||||
}
|
||||
|
||||
const rows = free.map((row, i) => (
|
||||
<tr key={i}>
|
||||
<td>{convertVar(row[0])}</td>
|
||||
<td>{convertVar(row[1])}</td>
|
||||
<td>{convertVar(row[2])}</td>
|
||||
</tr>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="four columns">
|
||||
<span>vBox</span>
|
||||
<table className="vbox-table">
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
</table>
|
||||
{JSON.stringify(vbox)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function InstanceComponent(props) {
|
||||
const {
|
||||
instance,
|
||||
account,
|
||||
sendInstanceReady,
|
||||
quit,
|
||||
} = props;
|
||||
|
||||
if (!instance) return <div>...</div>;
|
||||
|
||||
return (
|
||||
<section>
|
||||
<div className="row">
|
||||
<div className="six columns">
|
||||
<button
|
||||
className="instance-btn instance-ui-btn glow-btn"
|
||||
onClick={quit}>
|
||||
Menu
|
||||
</button>
|
||||
</div>
|
||||
<div className="six columns">
|
||||
<button
|
||||
className="instance-btn instance-ui-btn green-btn u-pull-right"
|
||||
onClick={() => sendInstanceReady()}>
|
||||
Ready
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
{Vbox(instance.vbox)}
|
||||
<div className="four columns">
|
||||
{JSON.stringify(instance.cryps)}
|
||||
</div>
|
||||
<div className="four columns">
|
||||
ready btn
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = InstanceComponent;
|
||||
@@ -0,0 +1,27 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const Instance = require('./instance.component');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, instance, account } = state;
|
||||
|
||||
function sendInstanceReady() {
|
||||
return ws.sendInstanceReady(instance.id);
|
||||
}
|
||||
|
||||
return { instance, account, sendInstanceReady };
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch, { instance }) {
|
||||
function quit() {
|
||||
dispatch(actions.setInstance(null));
|
||||
}
|
||||
return { quit };
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
module.exports = addState(Instance);
|
||||
@@ -0,0 +1,27 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const actions = require('../actions');
|
||||
|
||||
const InstanceList = require('./instance.list');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { ws, events, instances } = state;
|
||||
function setCrypsSet() {
|
||||
console.log('set crypos');
|
||||
// return ws.sendGamePvp(crypIds);
|
||||
}
|
||||
|
||||
return { instances, setCrypsSet };
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function setActiveInstance(instance) {
|
||||
dispatch(actions.setInstance(instance));
|
||||
}
|
||||
|
||||
return { setActiveInstance };
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = addState(InstanceList);
|
||||
@@ -0,0 +1,31 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
|
||||
const { NULL_UUID } = require('./../utils');
|
||||
|
||||
function instanceList({ instances, setActiveInstance, sendCrypsSet }) {
|
||||
if (!instances) return <div>...</div>;
|
||||
const instancePanels = instances.map((instance) => {
|
||||
const name = instance.instance === NULL_UUID
|
||||
? 'Normal Mode'
|
||||
: `${instance.instance.substring(0, 5)}`;
|
||||
|
||||
return (
|
||||
<button
|
||||
className="instance-btn glow-btn"
|
||||
key={instance.id}
|
||||
onClick={() => setActiveInstance(instance)}>
|
||||
{name}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<section>
|
||||
<h2>Instances</h2>
|
||||
{instancePanels}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = instanceList;
|
||||
@@ -0,0 +1,20 @@
|
||||
const { connect } = require('preact-redux');
|
||||
const actions = require('../actions');
|
||||
|
||||
const ItemList = require('./item.list');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const { items } = state;
|
||||
return { items };
|
||||
},
|
||||
function receiveDispatch(dispatch) {
|
||||
function setActiveItem(id) {
|
||||
dispatch(actions.setActiveItem(id))
|
||||
}
|
||||
|
||||
return { setActiveItem };
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = addState(ItemList);
|
||||
@@ -0,0 +1,37 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
|
||||
function ItemList({ items, setActiveItem }) {
|
||||
if (!items) return <div>...</div>;
|
||||
const itemPanels = items.map(item => (
|
||||
|
||||
<div key={item.id} className="tile is-parent is-vertical">
|
||||
<div className="tile is-vertical is-child">
|
||||
<div className="columns" >
|
||||
<div className="column is-8">
|
||||
<p className="title">{item.action}</p>
|
||||
<p className="subtitle">∞</p>
|
||||
</div>
|
||||
<div className="column">
|
||||
<figure className="image">
|
||||
<svg width="40" height="40" data-jdenticon-value={item.action} />
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="button is-dark"
|
||||
type="submit"
|
||||
onClick={() => setActiveItem(item.id)}>
|
||||
Use
|
||||
</button>
|
||||
</div>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
{itemPanels}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ItemList;
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// eslint-disable-next-line
|
||||
const preact = require('preact');
|
||||
|
||||
function renderLogin({ account, submitLogin, submitRegister }) {
|
||||
if (account) return (
|
||||
<div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" className="ping-svg">
|
||||
<path d="M0,50l50,-50v100l50,-50" className="ping-path"/>
|
||||
<path d="M0,50l50,-50v100l50,-50" className="ping-path"/>
|
||||
</svg>
|
||||
<h3 className="header-username">{account.name}</h3>
|
||||
</div>
|
||||
);
|
||||
|
||||
const details = {
|
||||
name: '',
|
||||
password: '',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="login" >
|
||||
<div className="field">
|
||||
<p className="control has-icons-left has-icons-right">
|
||||
<input
|
||||
className="input"
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
onChange={e => (details.name = e.target.value)}
|
||||
/>
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-user" />
|
||||
</span>
|
||||
<span className="icon is-small is-right">
|
||||
<i className="fas fa-check" />
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="field">
|
||||
<p className="control has-icons-left">
|
||||
<input
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
onChange={e => (details.password = e.target.value)}
|
||||
/>
|
||||
<span className="icon is-small is-left">
|
||||
<i className="fas fa-lock" />
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="field">
|
||||
<p className="control">
|
||||
<button
|
||||
className="button inverted"
|
||||
type="submit"
|
||||
onClick={() => submitLogin('ntr', 'grepgrepgrep')}>
|
||||
Default
|
||||
</button>
|
||||
<button
|
||||
className="button inverted"
|
||||
type="submit"
|
||||
onClick={() => submitLogin(details.name, details.password)}>
|
||||
Login
|
||||
</button>
|
||||
<button
|
||||
className="button inverted"
|
||||
type="submit"
|
||||
onClick={() => submitRegister(details.name, details.password)}>
|
||||
Register
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = renderLogin;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const Login = require('./login.component');
|
||||
|
||||
const addState = connect(
|
||||
(state) => {
|
||||
const { ws } = state;
|
||||
function submitLogin(name, password) {
|
||||
return ws.sendAccountLogin(name, password);
|
||||
}
|
||||
function submitRegister(name, password) {
|
||||
return ws.sendAccountRegister(name, password);
|
||||
}
|
||||
return { account: state.account, submitLogin, submitRegister };
|
||||
},
|
||||
);
|
||||
|
||||
module.exports = addState(Login);
|
||||
@@ -0,0 +1,47 @@
|
||||
const preact = require('preact');
|
||||
|
||||
// components all the way down
|
||||
const Icon = name => (
|
||||
<span>
|
||||
{name}
|
||||
<svg width="80" height="80" data-jdenticon-value={name} />
|
||||
</span>
|
||||
);
|
||||
|
||||
// the css attribute name `class` is reserved in js
|
||||
// so in react you have to call it `className`
|
||||
function Navbar() {
|
||||
const NAMES = ['Mashy', 'ntr'];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<nav className="navbar">
|
||||
<div className="navbar-end">
|
||||
<a href="/somewhere" className="navbar-item is-active">
|
||||
Home
|
||||
</a>
|
||||
<a href="/somewhere" className="navbar-item">
|
||||
Store
|
||||
</a>
|
||||
<a href="/somewhere" className="navbar-item">
|
||||
FAQ
|
||||
</a>
|
||||
<span className="navbar-item">
|
||||
<a href="/somewhere" className="button is-info is-inverted">
|
||||
<span className="icon">
|
||||
<svg width="80" height="80" data-jdenticon-value="Blog" />
|
||||
</span>
|
||||
<span>Blog</span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
{NAMES.map(Icon)}
|
||||
</div>
|
||||
);
|
||||
// map is a function that is called on every element of an array
|
||||
// so in this ^^ case it calls Icon('Mashy') which returns some jsx
|
||||
// that gets put into the dom
|
||||
}
|
||||
|
||||
module.exports = Navbar;
|
||||
@@ -0,0 +1,205 @@
|
||||
const toast = require('izitoast');
|
||||
|
||||
const actions = require('./actions');
|
||||
|
||||
function registerEvents(store) {
|
||||
function setCryps(cryps) {
|
||||
console.log('EVENT ->', 'cryps', cryps);
|
||||
}
|
||||
|
||||
function setCrypList(cryps) {
|
||||
store.dispatch(actions.setCryps(cryps));
|
||||
}
|
||||
|
||||
function setWs(ws) {
|
||||
console.log('EVENT ->', 'ws', ws);
|
||||
}
|
||||
|
||||
function setGame(game) {
|
||||
return console.log('EVENT ->', 'game', game);
|
||||
}
|
||||
|
||||
function setAccount(account) {
|
||||
store.dispatch(actions.setAccount(account));
|
||||
}
|
||||
|
||||
function setActiveSkill(skill) {
|
||||
console.log('EVENT ->', 'activeSkill', skill);
|
||||
}
|
||||
|
||||
function setMenu() {
|
||||
console.log('EVENT ->', 'menu', true);
|
||||
}
|
||||
|
||||
function setVbox(items) {
|
||||
console.log('EVENT ->', 'vbox', items);
|
||||
}
|
||||
|
||||
function setScores(scores) {
|
||||
console.log('EVENT ->', 'scores', scores);
|
||||
}
|
||||
|
||||
function setInstanceList(v) {
|
||||
return store.dispatch(actions.setInstances(v));
|
||||
}
|
||||
|
||||
function setPlayer(player) {
|
||||
console.log('EVENT ->', 'player', player);
|
||||
}
|
||||
|
||||
function setZone(zone) {
|
||||
console.log('EVENT ->', 'zone', zone);
|
||||
}
|
||||
|
||||
function setGameList(gameList) {
|
||||
console.log('EVENT ->', 'gameList', gameList);
|
||||
}
|
||||
|
||||
function setCrypStatusUpdate(id, skill, target) {
|
||||
console.log('EVENT ->', 'crypStatusUpdate', { id, skill, target });
|
||||
}
|
||||
|
||||
// events.on('SET_PLAYER', setPlayer);
|
||||
|
||||
// events.on('SEND_SKILL', function skillActive(gameId, crypId, targetCrypId, skill) {
|
||||
// ws.sendGameSkill(gameId, crypId, targetCrypId, skill);
|
||||
// setCrypStatusUpdate(crypId, skill, targetCrypId);
|
||||
// });
|
||||
|
||||
// events.on('CRYP_ACTIVE', function crypActiveCb(cryp) {
|
||||
// for (let i = 0; i < cryps.length; i += 1) {
|
||||
// if (cryps[i].id === cryp.id) cryps[i].active = !cryps[i].active;
|
||||
// }
|
||||
// return setCryps(cryps);
|
||||
// });
|
||||
|
||||
const errMessages = {
|
||||
select_cryps: 'Select your cryps before battle using the numbered buttons next to the cryp avatar',
|
||||
complete_nodes: 'You need to complete the previously connected nodes first',
|
||||
max_skills: 'Your cryp can only learn a maximum of 4 skills',
|
||||
|
||||
};
|
||||
|
||||
function errorPrompt(type) {
|
||||
const message = errMessages[type];
|
||||
const OK_BUTTON = '<button type="submit">OK</button>';
|
||||
toast.info({
|
||||
theme: 'dark',
|
||||
color: 'black',
|
||||
timeout: false,
|
||||
drag: false,
|
||||
position: 'center',
|
||||
maxWidth: window.innerWidth / 2,
|
||||
close: false,
|
||||
buttons: [
|
||||
[OK_BUTTON, (instance, thisToast) => instance.hide({ transitionOut: 'fadeOut' }, thisToast)],
|
||||
],
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
||||
// function loginPrompt() {
|
||||
// const USER_INPUT = '<input className="input" type="email" placeholder="username" />';
|
||||
// const PASSWORD_INPUT = '<input className="input" type="password" placeholder="password" />';
|
||||
// const LOGIN_BUTTON = '<button type="submit">Login</button>';
|
||||
// const REGISTER_BUTTON = '<button type="submit">Register</button>';
|
||||
// const DEMO_BUTTON = '<button type="submit">Demo</button>';
|
||||
|
||||
// const ws = registry.get('ws');
|
||||
|
||||
// function submitLogin(instance, thisToast, button, e, inputs) {
|
||||
// const USERNAME = inputs[0].value;
|
||||
// const PASSWORD = inputs[1].value;
|
||||
// ws.sendAccountLogin(USERNAME, PASSWORD);
|
||||
// }
|
||||
|
||||
// function submitRegister(instance, thisToast, button, e, inputs) {
|
||||
// const USERNAME = inputs[0].value;
|
||||
// const PASSWORD = inputs[1].value;
|
||||
// ws.sendAccountCreate(USERNAME, PASSWORD);
|
||||
// }
|
||||
|
||||
// function submitDemo() {
|
||||
// ws.sendAccountDemo();
|
||||
// }
|
||||
|
||||
// const existing = document.querySelector('#login'); // Selector of your toast
|
||||
// if (existing) toast.hide({}, existing, 'reconnect');
|
||||
|
||||
// toast.question({
|
||||
// id: 'login',
|
||||
// theme: 'dark',
|
||||
// color: 'black',
|
||||
// timeout: false,
|
||||
// // overlay: true,
|
||||
// drag: false,
|
||||
// close: false,
|
||||
// title: 'LOGIN',
|
||||
// position: 'center',
|
||||
// inputs: [
|
||||
// [USER_INPUT, 'change', () => true, true], // true to focus
|
||||
// [PASSWORD_INPUT, 'change', () => true],
|
||||
// ],
|
||||
// buttons: [
|
||||
// [LOGIN_BUTTON, submitLogin], // true to focus
|
||||
// [REGISTER_BUTTON, submitRegister], // true to focus
|
||||
// [DEMO_BUTTON, submitDemo], // true to focus
|
||||
// ],
|
||||
// });
|
||||
|
||||
// console.log('ACCOUNT', function closeLoginCb() {
|
||||
// const prompt = document.querySelector('#login'); // Selector of your toast
|
||||
// if (prompt) toast.hide({ transitionOut: 'fadeOut' }, prompt, 'EVENT ->');
|
||||
// });
|
||||
// }
|
||||
|
||||
// events.on('CRYP_SPAWN', function spawnPrompt() {
|
||||
// const NAME_INPUT = '<input className="input" type="email" placeholder="name" />';
|
||||
// const SPAWN_BUTTON = '<button type="submit">SPAWN</button>';
|
||||
|
||||
// const ws = registry.get('ws');
|
||||
|
||||
// function submitSpawn(instance, thisToast, button, e, inputs) {
|
||||
// const NAME = inputs[0].value;
|
||||
// ws.sendCrypSpawn(NAME);
|
||||
// instance.hide({ transitionOut: 'fadeOut' }, thisToast, 'button');
|
||||
// }
|
||||
|
||||
// toast.question({
|
||||
// theme: 'dark',
|
||||
// color: 'black',
|
||||
// timeout: false,
|
||||
// // overlay: true,
|
||||
// drag: false,
|
||||
// close: true,
|
||||
// title: 'SPAWN CRYP',
|
||||
// position: 'center',
|
||||
// inputs: [
|
||||
// [NAME_INPUT, 'change', null, true], // true to focus
|
||||
// ],
|
||||
// buttons: [
|
||||
// [SPAWN_BUTTON, submitSpawn], // true to focus
|
||||
// ],
|
||||
// });
|
||||
// });
|
||||
|
||||
return {
|
||||
errorPrompt,
|
||||
// loginPrompt,
|
||||
setAccount,
|
||||
setActiveSkill,
|
||||
setCryps,
|
||||
setCrypList,
|
||||
setGame,
|
||||
setMenu,
|
||||
setPlayer,
|
||||
setInstanceList,
|
||||
setVbox,
|
||||
setWs,
|
||||
setGameList,
|
||||
setZone,
|
||||
setScores,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = registerEvents;
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
const key = require('keymaster');
|
||||
const actions = require('./actions');
|
||||
|
||||
function setupKeys(store) {
|
||||
store.subscribe(() => {
|
||||
const state = store.getState();
|
||||
|
||||
key.unbind('esc');
|
||||
|
||||
if (state.activeItem) {
|
||||
key('esc', () => store.dispatch(actions.setActiveItem(null)));
|
||||
}
|
||||
if (state.activeSkill) {
|
||||
key('esc', () => store.dispatch(actions.setActiveSkill(null)));
|
||||
}
|
||||
if (state.activeIncoming) {
|
||||
key('esc', () => store.dispatch(actions.setActiveIncoming(null)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = setupKeys;
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
const preact = require('preact');
|
||||
const jdenticon = require('jdenticon');
|
||||
|
||||
const { Provider } = require('preact-redux');
|
||||
const { createStore, combineReducers } = require('redux');
|
||||
|
||||
const reducers = require('./reducers');
|
||||
const actions = require('./actions');
|
||||
// const setupKeys = require('./keyboard');
|
||||
// const fizzyText = require('../lib/fizzy-text');
|
||||
const createSocket = require('./socket');
|
||||
const registerEvents = require('./events');
|
||||
|
||||
const Header = require('./components/header.component');
|
||||
const Body = require('./components/body.component');
|
||||
|
||||
// Redux Store
|
||||
const store = createStore(
|
||||
combineReducers({
|
||||
account: reducers.accountReducer,
|
||||
game: reducers.gameReducer,
|
||||
cryps: reducers.crypsReducer,
|
||||
instances: reducers.instancesReducer,
|
||||
instance: reducers.instanceReducer,
|
||||
ws: reducers.wsReducer,
|
||||
})
|
||||
);
|
||||
|
||||
document.fonts.load('10pt "Jura"').then(() => {
|
||||
const events = registerEvents(store);
|
||||
store.subscribe(() => console.log(store.getState()));
|
||||
// setupKeys(store);
|
||||
|
||||
const ws = createSocket(events);
|
||||
store.dispatch(actions.setWs(ws));
|
||||
ws.connect();
|
||||
|
||||
// tells jdenticon to look for new svgs and render them
|
||||
// so we don't have to setInnerHtml or manually call update
|
||||
jdenticon.config = {
|
||||
replaceMode: 'observe',
|
||||
};
|
||||
|
||||
const Cryps = () => (
|
||||
<section>
|
||||
<Header />
|
||||
<Body />
|
||||
</section>
|
||||
);
|
||||
|
||||
const Main = () => (
|
||||
<Provider store={store}>
|
||||
<Cryps />
|
||||
</Provider>
|
||||
);
|
||||
|
||||
// eslint-disable-next-line
|
||||
preact.render(<Main />, document.body);
|
||||
|
||||
// fizzyText('cryps.gg');
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
const actions = require('./actions');
|
||||
|
||||
const defaultAccount = null;
|
||||
function accountReducer(state = defaultAccount, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_ACCOUNT:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultCryps = null;
|
||||
function crypsReducer(state = defaultCryps, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_CRYPS:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultInstances = null;
|
||||
function instancesReducer(state = defaultInstances, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_INSTANCES:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultInstance = null;
|
||||
function instanceReducer(state = defaultInstance, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_INSTANCE:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultGame = null;
|
||||
function gameReducer(state = defaultGame, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_GAME:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultWs = null;
|
||||
function wsReducer(state = defaultWs, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_WS:
|
||||
return action.value;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
accountReducer,
|
||||
crypsReducer,
|
||||
gameReducer,
|
||||
instancesReducer,
|
||||
instanceReducer,
|
||||
wsReducer,
|
||||
};
|
||||
Executable
+321
@@ -0,0 +1,321 @@
|
||||
const toast = require('izitoast');
|
||||
const cbor = require('borc');
|
||||
|
||||
|
||||
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://cryps.gg/ws' : 'ws://localhost:40000';
|
||||
|
||||
function errorToast(err) {
|
||||
console.error(err);
|
||||
return toast.error({
|
||||
title: 'BEEP BOOP',
|
||||
message: err,
|
||||
position: 'topRight',
|
||||
});
|
||||
}
|
||||
|
||||
function createSocket(events) {
|
||||
let ws;
|
||||
|
||||
// handle account auth within the socket itself
|
||||
// https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html
|
||||
let account = null;
|
||||
|
||||
// -------------
|
||||
// Outgoing
|
||||
// -------------
|
||||
function send(msg) {
|
||||
console.log('outgoing msg', msg);
|
||||
msg.token = account && account.token;
|
||||
ws.send(cbor.encode(msg));
|
||||
}
|
||||
|
||||
function sendAccountLogin(name, password) {
|
||||
send({ method: 'account_login', params: { name, password } });
|
||||
}
|
||||
|
||||
function sendAccountCreate(name, password) {
|
||||
send({ method: 'account_create', params: { name, password } });
|
||||
}
|
||||
|
||||
function sendAccountDemo() {
|
||||
send({ method: 'account_demo', params: {} });
|
||||
}
|
||||
|
||||
function sendAccountCryps() {
|
||||
send({ method: 'account_cryps', params: {} });
|
||||
}
|
||||
|
||||
function sendAccountPlayers() {
|
||||
send({ method: 'account_players', params: {} });
|
||||
}
|
||||
|
||||
function sendAccountZone() {
|
||||
send({ method: 'account_zone', params: {} });
|
||||
}
|
||||
|
||||
function sendCrypSpawn(name) {
|
||||
send({ method: 'cryp_spawn', params: { name } });
|
||||
}
|
||||
|
||||
function sendCrypLearn(id, skill) {
|
||||
send({ method: 'cryp_learn', params: { id, skill } });
|
||||
}
|
||||
|
||||
function sendCrypForget(id, skill) {
|
||||
send({ method: 'cryp_forget', params: { id, skill } });
|
||||
}
|
||||
|
||||
function sendGameState(id) {
|
||||
send({ method: 'game_state', params: { id } });
|
||||
}
|
||||
|
||||
function sendGameJoin(gameId, crypIds) {
|
||||
send({ method: 'game_join', params: { game_id: gameId, cryp_ids: crypIds } });
|
||||
}
|
||||
|
||||
function sendSpecForget(id, spec) {
|
||||
send({ method: 'cryp_unspec', params: { id, spec } });
|
||||
}
|
||||
|
||||
function sendPlayerCrypsSet(instanceId, crypIds) {
|
||||
send({ method: 'player_cryps_set', params: { instance_id: instanceId, cryp_ids: crypIds } });
|
||||
}
|
||||
|
||||
function sendPlayerState(instanceId) {
|
||||
send({ method: 'player_state', params: { instance_id: instanceId } });
|
||||
}
|
||||
|
||||
function sendVboxAccept(instanceId, group, index) {
|
||||
send({ method: 'player_vbox_accept', params: { instance_id: instanceId, group, index } });
|
||||
}
|
||||
|
||||
function sendVboxApply(instanceId, crypId, index) {
|
||||
send({ method: 'player_vbox_apply', params: { instance_id: instanceId, cryp_id: crypId, index } });
|
||||
}
|
||||
|
||||
function sendVboxUnequip(instanceId, crypId, target) {
|
||||
send({ method: 'player_vbox_unequip', params: { instance_id: instanceId, cryp_id: crypId, target } });
|
||||
}
|
||||
|
||||
function sendVboxDiscard(instanceId) {
|
||||
send({ method: 'player_vbox_discard', params: { instance_id: instanceId } });
|
||||
}
|
||||
|
||||
function sendVboxCombine(instanceId, indices) {
|
||||
send({ method: 'player_vbox_combine', params: { instance_id: instanceId, indices } });
|
||||
}
|
||||
|
||||
function sendVboxReclaim(instanceId, index) {
|
||||
send({ method: 'player_vbox_reclaim', params: { instance_id: instanceId, index } });
|
||||
}
|
||||
|
||||
function sendGameSkill(gameId, crypId, targetCrypId, skill) {
|
||||
send({
|
||||
method: 'game_skill',
|
||||
params: {
|
||||
game_id: gameId, cryp_id: crypId, target_cryp_id: targetCrypId, skill,
|
||||
},
|
||||
});
|
||||
events.setActiveSkill(null);
|
||||
}
|
||||
|
||||
function sendGameTarget(gameId, crypId, skillId) {
|
||||
send({ method: 'game_target', params: { game_id: gameId, cryp_id: crypId, skill_id: skillId } });
|
||||
events.setActiveSkill(null);
|
||||
}
|
||||
|
||||
function sendZoneCreate() {
|
||||
send({ method: 'zone_create', params: {} });
|
||||
}
|
||||
|
||||
function sendZoneJoin(zoneId, nodeId, crypIds) {
|
||||
send({ method: 'zone_join', params: { zone_id: zoneId, node_id: nodeId, cryp_ids: crypIds } });
|
||||
}
|
||||
|
||||
function sendZoneClose(zoneId) {
|
||||
send({ method: 'zone_close', params: { zone_id: zoneId } });
|
||||
}
|
||||
|
||||
function sendInstanceJoin(cryps) {
|
||||
send({ method: 'instance_join', params: { cryp_ids: cryps, pve: true } });
|
||||
}
|
||||
|
||||
function sendInstanceReady(instanceId) {
|
||||
send({ method: 'instance_ready', params: { instance_id: instanceId } });
|
||||
}
|
||||
|
||||
function sendInstanceScores(instanceId) {
|
||||
send({ method: 'instance_scores', params: { instance_id: instanceId } });
|
||||
}
|
||||
|
||||
|
||||
// -------------
|
||||
// Incoming
|
||||
// -------------
|
||||
function accountLogin(res) {
|
||||
const [struct, login] = res;
|
||||
|
||||
account = login;
|
||||
events.setAccount(login);
|
||||
sendAccountCryps();
|
||||
sendAccountPlayers();
|
||||
}
|
||||
|
||||
function accountPlayerList(res) {
|
||||
const [struct, playerList] = res;
|
||||
events.setInstanceList(playerList);
|
||||
}
|
||||
|
||||
function accountCryps(response) {
|
||||
const [structName, cryps] = response;
|
||||
events.setCrypList(cryps);
|
||||
}
|
||||
|
||||
function gameState(response) {
|
||||
const [structName, game] = response;
|
||||
events.setGame(game);
|
||||
}
|
||||
|
||||
function crypSpawn(response) {
|
||||
const [structName, cryp] = response;
|
||||
}
|
||||
|
||||
function zoneState(response) {
|
||||
const [structName, zone] = response;
|
||||
events.setZone(zone);
|
||||
}
|
||||
|
||||
function playerState(response) {
|
||||
const [structName, player] = response;
|
||||
events.setPlayer(player);
|
||||
}
|
||||
|
||||
function instanceScores(response) {
|
||||
const [structName, scores] = response;
|
||||
events.setScores(scores);
|
||||
}
|
||||
|
||||
// -------------
|
||||
// Setup
|
||||
// -------------
|
||||
|
||||
// when the server sends a reply it will have one of these message types
|
||||
// this object wraps the reply types to a function
|
||||
const handlers = {
|
||||
cryp_spawn: crypSpawn,
|
||||
cryp_forget: () => true,
|
||||
cryp_learn: () => true,
|
||||
game_state: gameState,
|
||||
account_login: accountLogin,
|
||||
account_create: accountLogin,
|
||||
account_cryps: accountCryps,
|
||||
account_players: accountPlayerList,
|
||||
instance_scores: instanceScores,
|
||||
zone_create: res => console.log(res),
|
||||
zone_state: zoneState,
|
||||
zone_close: res => console.log(res),
|
||||
player_state: playerState,
|
||||
};
|
||||
|
||||
function errHandler(error) {
|
||||
switch (error) {
|
||||
case 'no active zone': return sendZoneCreate();
|
||||
case 'no cryps selected': return events.errorPrompt('select_cryps');
|
||||
case 'node requirements not met': return events.errorPrompt('complete_nodes');
|
||||
case 'cryp at max skills (4)': return events.errorPrompt('max_skills');
|
||||
|
||||
default: return errorToast(error);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// decodes the cbor and
|
||||
// calls the handlers defined above based on message type
|
||||
function onMessage(event) {
|
||||
// decode binary msg from server
|
||||
const blob = new Uint8Array(event.data);
|
||||
const res = cbor.decode(blob);
|
||||
const { method, params } = res;
|
||||
|
||||
console.log(res);
|
||||
|
||||
// check for error and split into response type and data
|
||||
if (res.err) return errHandler(res.err);
|
||||
if (!handlers[method]) return errorToast(`${method} handler missing`);
|
||||
return handlers[method](params);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
ws = new WebSocket(SOCKET_URL);
|
||||
ws.binaryType = 'arraybuffer';
|
||||
|
||||
// Connection opened
|
||||
ws.addEventListener('open', () => {
|
||||
toast.info({
|
||||
message: 'connected',
|
||||
position: 'topRight',
|
||||
});
|
||||
|
||||
// if (!account) events.loginPrompt();
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
send({ method: 'account_login', params: { name: 'ntr', password: 'grepgrepgrep' } });
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Listen for messages
|
||||
ws.addEventListener('message', onMessage);
|
||||
|
||||
ws.addEventListener('error', (event) => {
|
||||
console.error('WebSocket error', event);
|
||||
// account = null;
|
||||
// return setTimeout(connect, 5000);
|
||||
});
|
||||
|
||||
ws.addEventListener('close', (event) => {
|
||||
console.error('WebSocket closed', event);
|
||||
toast.warning({
|
||||
message: 'disconnected',
|
||||
position: 'topRight',
|
||||
});
|
||||
return setTimeout(connect, 5000);
|
||||
});
|
||||
|
||||
return ws;
|
||||
}
|
||||
|
||||
return {
|
||||
sendAccountLogin,
|
||||
sendAccountCreate,
|
||||
sendAccountDemo,
|
||||
sendAccountCryps,
|
||||
sendAccountPlayers,
|
||||
sendAccountZone,
|
||||
sendGameState,
|
||||
sendGameJoin,
|
||||
sendGameSkill,
|
||||
sendGameTarget,
|
||||
sendCrypSpawn,
|
||||
sendCrypLearn,
|
||||
sendCrypForget,
|
||||
sendSpecForget,
|
||||
sendZoneCreate,
|
||||
sendZoneJoin,
|
||||
sendZoneClose,
|
||||
sendInstanceJoin,
|
||||
sendInstanceReady,
|
||||
sendInstanceScores,
|
||||
sendPlayerCrypsSet,
|
||||
sendPlayerState,
|
||||
sendVboxAccept,
|
||||
sendVboxApply,
|
||||
sendVboxReclaim,
|
||||
sendVboxCombine,
|
||||
sendVboxDiscard,
|
||||
sendVboxUnequip,
|
||||
connect,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = createSocket;
|
||||
@@ -0,0 +1,61 @@
|
||||
const get = require('lodash/get');
|
||||
|
||||
const stringSort = (k, desc) => {
|
||||
if (desc) {
|
||||
return (a, b) => {
|
||||
if (!get(a, k)) return 1;
|
||||
if (!get(b, k)) return -1;
|
||||
return get(b, k).localeCompare(get(a, k));
|
||||
};
|
||||
}
|
||||
return (a, b) => {
|
||||
if (!get(a, k)) return 1;
|
||||
if (!get(b, k)) return -1;
|
||||
return get(a, k).localeCompare(get(b, k));
|
||||
};
|
||||
};
|
||||
|
||||
const numSort = (k, desc) => {
|
||||
if (desc) {
|
||||
return (a, b) => {
|
||||
if (!get(a, k)) return 1;
|
||||
if (!get(b, k)) return -1;
|
||||
return get(b, k) - get(a, k);
|
||||
};
|
||||
}
|
||||
return (a, b) => {
|
||||
if (!get(a, k)) return 1;
|
||||
if (!get(b, k)) return -1;
|
||||
return get(a, k) - get(b, k);
|
||||
};
|
||||
};
|
||||
|
||||
const genAvatar = (name) => {
|
||||
let hash = 0;
|
||||
if (name.length === 0) return hash;
|
||||
// Probs don't need to hash using the whole string
|
||||
for (let i = 0; i < name.length; i += 1) {
|
||||
const chr = name.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + chr;
|
||||
hash = hash & 10000; // We have avatars named 0-19
|
||||
}
|
||||
return `sprite${hash}`;
|
||||
};
|
||||
|
||||
function requestAvatar(name) {
|
||||
const id = genAvatar(name);
|
||||
const req = new Request(`/assets/molecules/${id}.svg`);
|
||||
return fetch(req)
|
||||
.then(res => res.text())
|
||||
.then(svg => svg);
|
||||
}
|
||||
|
||||
const NULL_UUID = '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
module.exports = {
|
||||
stringSort,
|
||||
numSort,
|
||||
genAvatar,
|
||||
requestAvatar,
|
||||
NULL_UUID,
|
||||
};
|
||||
Reference in New Issue
Block a user