eslint auto-fix
This commit is contained in:
parent
aa8c666ceb
commit
520dc1655e
|
@ -671,4 +671,3 @@ export function switchCanvas(canvasId: number): PromiseAction {
|
||||||
dispatch(onViewFinishChange());
|
dispatch(onViewFinishChange());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,10 +52,7 @@ export type Action =
|
||||||
| { type: 'SHOW_MODAL', modalType: string, modalProps: obj }
|
| { type: 'SHOW_MODAL', modalType: string, modalProps: obj }
|
||||||
| { type: 'HIDE_MODAL' }
|
| { type: 'HIDE_MODAL' }
|
||||||
| { type: 'RELOAD_URL' }
|
| { type: 'RELOAD_URL' }
|
||||||
| { type: 'ON_VIEW_FINISH_CHANGE' }
|
| { type: 'ON_VIEW_FINISH_CHANGE' };
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
export type PromiseAction = Promise<Action>;
|
export type PromiseAction = Promise<Action>;
|
||||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
||||||
export type Dispatch = (action: Action | ThunkAction | PromiseAction | Array<Action>) => any;
|
export type Dispatch = (action: Action | ThunkAction | PromiseAction | Array<Action>) => any;
|
||||||
|
|
|
@ -132,8 +132,9 @@ function initViewport() {
|
||||||
let lastScale = initialState.canvas.scale;
|
let lastScale = initialState.canvas.scale;
|
||||||
hammertime.on(
|
hammertime.on(
|
||||||
'panstart pinchstart pan pinch panend pinchend',
|
'panstart pinchstart pan pinch panend pinchend',
|
||||||
({ type, deltaX, deltaY, scale },
|
({
|
||||||
) => {
|
type, deltaX, deltaY, scale,
|
||||||
|
}) => {
|
||||||
viewport.style.cursor = 'move'; // like google maps
|
viewport.style.cursor = 'move'; // like google maps
|
||||||
const { scale: viewportScale } = store.getState().canvas;
|
const { scale: viewportScale } = store.getState().canvas;
|
||||||
|
|
||||||
|
@ -192,7 +193,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const renderer = new Renderer();
|
const renderer = new Renderer();
|
||||||
renderer.setViewport(viewport);
|
renderer.setViewport(viewport);
|
||||||
|
|
||||||
ProtocolClient.on('pixelUpdate', ({ i, j, offset, color }) => {
|
ProtocolClient.on('pixelUpdate', ({
|
||||||
|
i, j, offset, color,
|
||||||
|
}) => {
|
||||||
store.dispatch(receivePixelUpdate(i, j, offset, color));
|
store.dispatch(receivePixelUpdate(i, j, offset, color));
|
||||||
// render updated pixel
|
// render updated pixel
|
||||||
renderer.renderPixel(i, j, offset, color);
|
renderer.renderPixel(i, j, offset, color);
|
||||||
|
|
|
@ -44,7 +44,6 @@ const data = {
|
||||||
description: 'admin access on pixelplanet',
|
description: 'admin access on pixelplanet',
|
||||||
body: <Admin />,
|
body: <Admin />,
|
||||||
};
|
};
|
||||||
const adminHtml =
|
const adminHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
||||||
`<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
|
||||||
|
|
||||||
export default adminHtml;
|
export default adminHtml;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { validateName, validateEMail, validatePassword, parseAPIresponse } from '../utils/validation';
|
import {
|
||||||
|
validateName, validateEMail, validatePassword, parseAPIresponse,
|
||||||
|
} from '../utils/validation';
|
||||||
|
|
||||||
function validate(email, password) {
|
function validate(email, password) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
@ -87,19 +89,19 @@ class ChangeMail extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={evt => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.email}
|
value={this.state.email}
|
||||||
onChange={evt => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="New Mail"
|
placeholder="New Mail"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -74,12 +74,12 @@ class ChangeName extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.name}
|
value={this.state.name}
|
||||||
onChange={evt => this.setState({ name: evt.target.value })}
|
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="New Username"
|
placeholder="New Username"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -60,7 +60,9 @@ class ChangePassword extends React.Component {
|
||||||
async handleSubmit(e) {
|
async handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { password, new_password, confirm_password, submitting } = this.state;
|
const {
|
||||||
|
password, new_password, confirm_password, submitting,
|
||||||
|
} = this.state;
|
||||||
if (submitting) return;
|
if (submitting) return;
|
||||||
|
|
||||||
const errors = validate(this.props.mailreg, password, new_password, confirm_password);
|
const errors = validate(this.props.mailreg, password, new_password, confirm_password);
|
||||||
|
@ -95,28 +97,29 @@ class ChangePassword extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
{(this.props.mailreg) &&
|
{(this.props.mailreg)
|
||||||
|
&& (
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={evt => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Old Password"
|
placeholder="Old Password"
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.new_password}
|
value={this.state.new_password}
|
||||||
onChange={evt => this.setState({ new_password: evt.target.value })}
|
onChange={(evt) => this.setState({ new_password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="New Password"
|
placeholder="New Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.confirm_password}
|
value={this.state.confirm_password}
|
||||||
onChange={evt => this.setState({ confirm_password: evt.target.value })}
|
onChange={(evt) => this.setState({ confirm_password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Confirm New Password"
|
placeholder="Confirm New Password"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -26,10 +26,11 @@ const Chat = ({ chatMessages }) => {
|
||||||
<div style={{ height: '100%' }}>
|
<div style={{ height: '100%' }}>
|
||||||
<ul className="chatarea" ref={listRef}>
|
<ul className="chatarea" ref={listRef}>
|
||||||
{
|
{
|
||||||
chatMessages.map(message => (
|
chatMessages.map((message) => (
|
||||||
<p className="chatmsg">
|
<p className="chatmsg">
|
||||||
{(message[0] == 'info') ?
|
{(message[0] == 'info')
|
||||||
<span style={{ color: '#cc0000' }}>{message[1]}</span> :
|
? <span style={{ color: '#cc0000' }}>{message[1]}</span>
|
||||||
|
: (
|
||||||
<div>
|
<div>
|
||||||
<span className="chatname" style={{ color: colorFromText(message[0]) }}>{`${message[0]}: `}</span>
|
<span className="chatname" style={{ color: colorFromText(message[0]) }}>{`${message[0]}: `}</span>
|
||||||
{
|
{
|
||||||
|
@ -39,7 +40,7 @@ const Chat = ({ chatMessages }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
</p>
|
</p>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,12 @@ import Chat from './Chat';
|
||||||
|
|
||||||
const ChatBox = ({ chatOpen }) => (
|
const ChatBox = ({ chatOpen }) => (
|
||||||
<div>
|
<div>
|
||||||
{(chatOpen) ?
|
{(chatOpen)
|
||||||
|
? (
|
||||||
<div className="chatbox">
|
<div className="chatbox">
|
||||||
<Chat />
|
<Chat />
|
||||||
</div> : null}
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ChatInput extends React.Component {
|
||||||
<input
|
<input
|
||||||
style={{ maxWidth: '80%', width: '240px' }}
|
style={{ maxWidth: '80%', width: '240px' }}
|
||||||
value={this.state.message}
|
value={this.state.message}
|
||||||
onChange={evt => this.setState({ message: evt.target.value })}
|
onChange={(evt) => this.setState({ message: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Chat here"
|
placeholder="Chat here"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -19,14 +19,15 @@ const DailyRankings = ({ totalDailyRanking }) => (
|
||||||
<th>Total Pixels</th>
|
<th>Total Pixels</th>
|
||||||
</tr>
|
</tr>
|
||||||
{
|
{
|
||||||
totalDailyRanking.map(rank => (
|
totalDailyRanking.map((rank) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{rank.dailyRanking}</td>
|
<td>{rank.dailyRanking}</td>
|
||||||
<td>{rank.name}</td>
|
<td>{rank.name}</td>
|
||||||
<td>{rank.dailyTotalPixels}</td>
|
<td>{rank.dailyTotalPixels}</td>
|
||||||
<td>{rank.ranking}</td>
|
<td>{rank.ranking}</td>
|
||||||
<td>{rank.totalPixels}</td>
|
<td>{rank.totalPixels}</td>
|
||||||
</tr>))
|
</tr>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -72,12 +72,12 @@ class DeleteAccount extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="inarea" style={{ backgroundColor: '#ff6666' }}>
|
<div className="inarea" style={{ backgroundColor: '#ff6666' }}>
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={evt => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -24,7 +24,7 @@ function download(view) {
|
||||||
const [x, y] = view.map(Math.round);
|
const [x, y] = view.map(Math.round);
|
||||||
const filename = `pixelplanet-${x}-${y}.png`;
|
const filename = `pixelplanet-${x}-${y}.png`;
|
||||||
|
|
||||||
$viewport.toBlob(blob => fileDownload(blob, filename));
|
$viewport.toBlob((blob) => fileDownload(blob, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ function globe(canvasId, canvasIdent, canvasSize, view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const GlobeButton = ({ canvasId, canvasIdent, canvasSize, view }) => (
|
const GlobeButton = ({
|
||||||
|
canvasId, canvasIdent, canvasSize, view,
|
||||||
|
}) => (
|
||||||
<div id="globebutton" className="actionbuttons" onClick={() => globe(canvasId, canvasIdent, canvasSize, view)}>
|
<div id="globebutton" className="actionbuttons" onClick={() => globe(canvasId, canvasIdent, canvasSize, view)}>
|
||||||
<Md3DRotation />
|
<Md3DRotation />
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,8 +29,12 @@ const GlobeButton = ({ canvasId, canvasIdent, canvasSize, view }) => (
|
||||||
|
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: State) {
|
||||||
const { canvasId, canvasIdent, canvasSize, view } = state.canvas;
|
const {
|
||||||
return { canvasId, canvasIdent, canvasSize, view };
|
canvasId, canvasIdent, canvasSize, view,
|
||||||
|
} = state.canvas;
|
||||||
|
return {
|
||||||
|
canvasId, canvasIdent, canvasSize, view,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(GlobeButton);
|
export default connect(mapStateToProps)(GlobeButton);
|
||||||
|
|
|
@ -31,7 +31,9 @@ class Html extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, description, styles, scripts, body, code, useRecaptcha } = this.props;
|
const {
|
||||||
|
title, description, styles, scripts, body, code, useRecaptcha,
|
||||||
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<html className="no-js" lang="en">
|
<html className="no-js" lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -45,14 +47,14 @@ class Html extends React.Component {
|
||||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||||
/>
|
/>
|
||||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||||
{styles.map(style =>
|
{styles.map((style) => (
|
||||||
(<style
|
<style
|
||||||
key={style.id}
|
key={style.id}
|
||||||
id={style.id}
|
id={style.id}
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{ __html: style.cssText }}
|
dangerouslySetInnerHTML={{ __html: style.cssText }}
|
||||||
/>),
|
/>
|
||||||
)}
|
))}
|
||||||
{RECAPTCHA_SITEKEY && useRecaptcha && <script dangerouslySetInnerHTML={{ __html: `window.sitekey="${RECAPTCHA_SITEKEY}"` }} />}
|
{RECAPTCHA_SITEKEY && useRecaptcha && <script dangerouslySetInnerHTML={{ __html: `window.sitekey="${RECAPTCHA_SITEKEY}"` }} />}
|
||||||
{RECAPTCHA_SITEKEY && useRecaptcha && <script src="https://www.google.com/recaptcha/api.js" async defer />}
|
{RECAPTCHA_SITEKEY && useRecaptcha && <script src="https://www.google.com/recaptcha/api.js" async defer />}
|
||||||
</head>
|
</head>
|
||||||
|
@ -64,18 +66,20 @@ class Html extends React.Component {
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{ __html: code }}
|
dangerouslySetInnerHTML={{ __html: code }}
|
||||||
/>
|
/>
|
||||||
{scripts.map(script => <script key={script} src={script} />)}
|
{scripts.map((script) => <script key={script} src={script} />)}
|
||||||
{analytics.google.trackingId &&
|
{analytics.google.trackingId
|
||||||
|
&& (
|
||||||
<script
|
<script
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{ __html:
|
dangerouslySetInnerHTML={{
|
||||||
'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;' +
|
__html:
|
||||||
`ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')` }}
|
'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;'
|
||||||
|
+ `ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')`,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
{analytics.google.trackingId &&
|
{analytics.google.trackingId
|
||||||
<script src="https://www.google-analytics.com/analytics.js" async defer />
|
&& <script src="https://www.google-analytics.com/analytics.js" async defer />}
|
||||||
}
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { validateEMail, validateName, validatePassword, parseAPIresponse } from '../utils/validation';
|
import {
|
||||||
|
validateEMail, validateName, validatePassword, parseAPIresponse,
|
||||||
|
} from '../utils/validation';
|
||||||
|
|
||||||
|
|
||||||
function validate(nameoremail, password) {
|
function validate(nameoremail, password) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const mailerror = (nameoremail.indexOf('@') !== -1) ?
|
const mailerror = (nameoremail.indexOf('@') !== -1)
|
||||||
validateEMail(nameoremail) :
|
? validateEMail(nameoremail)
|
||||||
validateName(nameoremail);
|
: validateName(nameoremail);
|
||||||
if (mailerror) errors.push(mailerror);
|
if (mailerror) errors.push(mailerror);
|
||||||
const passworderror = validatePassword(password);
|
const passworderror = validatePassword(password);
|
||||||
if (passworderror) errors.push(passworderror);
|
if (passworderror) errors.push(passworderror);
|
||||||
|
@ -80,20 +82,20 @@ class LogInForm extends React.Component {
|
||||||
const { errors } = this.state;
|
const { errors } = this.state;
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error}>Error: {error}</p>
|
<p key={error}>Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.nameoremail}
|
value={this.state.nameoremail}
|
||||||
onChange={evt => this.setState({ nameoremail: evt.target.value })}
|
onChange={(evt) => this.setState({ nameoremail: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Name or Email"
|
placeholder="Name or Email"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={evt => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,8 +14,8 @@ import { ASSET_SERVER } from '../core/config';
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
title: 'PixelPlanet.fun',
|
title: 'PixelPlanet.fun',
|
||||||
description: 'Place color pixels on an map styled canvas ' +
|
description: 'Place color pixels on an map styled canvas '
|
||||||
'with other players online',
|
+ 'with other players online',
|
||||||
// styles: [
|
// styles: [
|
||||||
// { id: 'css', cssText: baseCss },
|
// { id: 'css', cssText: baseCss },
|
||||||
// ],
|
// ],
|
||||||
|
@ -35,8 +35,7 @@ const data = {
|
||||||
*/
|
*/
|
||||||
function generateMainPage(countryCoords: Cell): string {
|
function generateMainPage(countryCoords: Cell): string {
|
||||||
const [x, y] = countryCoords;
|
const [x, y] = countryCoords;
|
||||||
const code =
|
const code = `window.coordx=${x};window.coordy=${y};window.assetserver="${ASSET_SERVER}";`;
|
||||||
`window.coordx=${x};window.coordy=${y};window.assetserver="${ASSET_SERVER}";`;
|
|
||||||
const htmldata = { ...data, code };
|
const htmldata = { ...data, code };
|
||||||
const html = ReactDOM.renderToStaticMarkup(<Html {...htmldata} />);
|
const html = ReactDOM.renderToStaticMarkup(<Html {...htmldata} />);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ const MdToggleButtonHover = ({ value, onToggle }) => (
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
}}
|
}}
|
||||||
animateThumbStyleHover={n => ({
|
animateThumbStyleHover={(n) => ({
|
||||||
boxShadow: `0 0 ${2 + (4 * n)}px rgba(0,0,0,.16),0 ${2 + (3 * n)}px ${4 + (8 * n)}px rgba(0,0,0,.32)`,
|
boxShadow: `0 0 ${2 + (4 * n)}px rgba(0,0,0,.16),0 ${2 + (3 * n)}px ${4 + (8 * n)}px rgba(0,0,0,.32)`,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -12,7 +12,9 @@ import DownloadButton from './DownloadButton';
|
||||||
import MinecraftTPButton from './MinecraftTPButton';
|
import MinecraftTPButton from './MinecraftTPButton';
|
||||||
import MinecraftButton from './MinecraftButton';
|
import MinecraftButton from './MinecraftButton';
|
||||||
|
|
||||||
const Menu = ({ menuOpen, minecraftname, messages, canvasId }) => (
|
const Menu = ({
|
||||||
|
menuOpen, minecraftname, messages, canvasId,
|
||||||
|
}) => (
|
||||||
<div>
|
<div>
|
||||||
{(menuOpen) ? <SettingsButton /> : null}
|
{(menuOpen) ? <SettingsButton /> : null}
|
||||||
{(menuOpen) ? <LogInButton /> : null}
|
{(menuOpen) ? <LogInButton /> : null}
|
||||||
|
@ -27,7 +29,9 @@ function mapStateToProps(state: State) {
|
||||||
const { menuOpen } = state.gui;
|
const { menuOpen } = state.gui;
|
||||||
const { minecraftname, messages } = state.user;
|
const { minecraftname, messages } = state.user;
|
||||||
const { canvasId } = state.canvas;
|
const { canvasId } = state.canvas;
|
||||||
return { menuOpen, minecraftname, messages, canvasId };
|
return {
|
||||||
|
menuOpen, minecraftname, messages, canvasId,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(Menu);
|
export default connect(mapStateToProps)(Menu);
|
||||||
|
|
|
@ -13,7 +13,7 @@ const MinecraftModal = () => (
|
||||||
<Modal title="PixelPlanet Minecraft Server">
|
<Modal title="PixelPlanet Minecraft Server">
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
<p>You can also place pixels from our Minecraft Server at</p>
|
<p>You can also place pixels from our Minecraft Server at</p>
|
||||||
<p><input type="text" value={'mc.pixelplanet.fun'} readOnly /></p>
|
<p><input type="text" value="mc.pixelplanet.fun" readOnly /></p>
|
||||||
<p>Please Note that the Minecraft Server is down from time to time</p>
|
<p>Please Note that the Minecraft Server is down from time to time</p>
|
||||||
</p>
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -38,5 +38,5 @@ const ModalRoot = ({ modalType, modalProps }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
state => state.modal,
|
(state) => state.modal,
|
||||||
)(ModalRoot);
|
)(ModalRoot);
|
||||||
|
|
|
@ -83,13 +83,13 @@ class NewPasswordForm extends React.Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error}>Error: {error}</p>
|
<p key={error}>Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.email}
|
value={this.state.email}
|
||||||
onChange={evt => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { numberToString } from '../core/utils';
|
|
||||||
import { FaUser, FaPaintBrush } from 'react-icons/fa';
|
import { FaUser, FaPaintBrush } from 'react-icons/fa';
|
||||||
|
import { numberToString } from '../core/utils';
|
||||||
|
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../reducers';
|
||||||
|
@ -14,12 +14,13 @@ import type { State } from '../reducers';
|
||||||
|
|
||||||
const OnlineBox = ({ online, totalPixels, name }) => (
|
const OnlineBox = ({ online, totalPixels, name }) => (
|
||||||
<div>
|
<div>
|
||||||
{(online || name) ?
|
{(online || name)
|
||||||
|
? (
|
||||||
<div className="onlinebox">
|
<div className="onlinebox">
|
||||||
{(online) && <span>{online} <FaUser /></span>}
|
{(online) && <span>{online} <FaUser /></span>}
|
||||||
{(name != null) && <span>{numberToString(totalPixels)} <FaPaintBrush /></span>}
|
{(name != null) && <span>{numberToString(totalPixels)} <FaPaintBrush /></span>}
|
||||||
</div> : null
|
</div>
|
||||||
}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -11,23 +11,28 @@ import { selectColor } from '../actions';
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../reducers';
|
||||||
|
|
||||||
|
|
||||||
const Palette = ({ colors, selectedColor, paletteOpen, compactPalette, select }) => (
|
const Palette = ({
|
||||||
|
colors, selectedColor, paletteOpen, compactPalette, select,
|
||||||
|
}) => (
|
||||||
<div className={`palettebox ${(compactPalette) ? 'compalette' : 'widpalette'}`} id="colors" style={{ display: (paletteOpen) ? 'flex' : 'none' }}>
|
<div className={`palettebox ${(compactPalette) ? 'compalette' : 'widpalette'}`} id="colors" style={{ display: (paletteOpen) ? 'flex' : 'none' }}>
|
||||||
{colors.slice(2).map((color, index) => (<span
|
{colors.slice(2).map((color, index) => (
|
||||||
|
<span
|
||||||
style={{ backgroundColor: color }}
|
style={{ backgroundColor: color }}
|
||||||
key={index + 2}
|
key={index + 2}
|
||||||
className={selectedColor === (index + 2) ? 'selected' : 'unselected'}
|
className={selectedColor === (index + 2) ? 'selected' : 'unselected'}
|
||||||
color={color}
|
color={color}
|
||||||
onClick={() => select(index + 2)}
|
onClick={() => select(index + 2)}
|
||||||
/>),
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: State) {
|
||||||
const { selectedColor, paletteOpen, compactPalette } = state.gui;
|
const { selectedColor, paletteOpen, compactPalette } = state.gui;
|
||||||
const { palette } = state.canvas;
|
const { palette } = state.canvas;
|
||||||
return { colors: palette.colors, selectedColor, paletteOpen, compactPalette };
|
return {
|
||||||
|
colors: palette.colors, selectedColor, paletteOpen, compactPalette,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
|
|
|
@ -10,7 +10,9 @@ import { MdPalette } from 'react-icons/md';
|
||||||
|
|
||||||
import { toggleOpenPalette } from '../actions';
|
import { toggleOpenPalette } from '../actions';
|
||||||
|
|
||||||
const PalselButton = ({ palette, onToggle, selectedColor, paletteOpen }) => (
|
const PalselButton = ({
|
||||||
|
palette, onToggle, selectedColor, paletteOpen,
|
||||||
|
}) => (
|
||||||
<div id="palselbutton" className={`actionbuttons ${(paletteOpen) ? '' : 'pressed'}`} style={{ color: palette.isDark(selectedColor) ? 'white' : 'black', backgroundColor: palette.colors[selectedColor] }} onClick={onToggle}>
|
<div id="palselbutton" className={`actionbuttons ${(paletteOpen) ? '' : 'pressed'}`} style={{ color: palette.isDark(selectedColor) ? 'white' : 'black', backgroundColor: palette.colors[selectedColor] }} onClick={onToggle}>
|
||||||
<MdPalette />
|
<MdPalette />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/server';
|
import ReactDOM from 'react-dom/server';
|
||||||
import Html from '../components/Html';
|
import Html from './Html';
|
||||||
|
|
||||||
const PasswordReset = ({ name, code }) => (
|
const PasswordReset = ({ name, code }) => (
|
||||||
<form method="post" action="reset_password">
|
<form method="post" action="reset_password">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/server';
|
import ReactDOM from 'react-dom/server';
|
||||||
import Html from '../components/Html';
|
import Html from './Html';
|
||||||
|
|
||||||
const RedirectionPage = ({ text }) => (
|
const RedirectionPage = ({ text }) => (
|
||||||
<div>
|
<div>
|
||||||
|
@ -25,4 +25,3 @@ export function getHtml(description, text) {
|
||||||
const index = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
const index = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,9 @@ const dividerStyles = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const SettingsItem = ({ title, description, keyBind, value, onToggle }) => (
|
const SettingsItem = ({
|
||||||
|
title, description, keyBind, value, onToggle,
|
||||||
|
}) => (
|
||||||
<div style={itemStyles}>
|
<div style={itemStyles}>
|
||||||
<div style={rowStyles}>
|
<div style={rowStyles}>
|
||||||
<h3 style={titleStyles}>{title} {keyBind && <kbd>{keyBind}</kbd>}</h3>
|
<h3 style={titleStyles}>{title} {keyBind && <kbd>{keyBind}</kbd>}</h3>
|
||||||
|
@ -154,11 +156,15 @@ function SettingsModal({
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: State) {
|
||||||
const { mute, chatNotify } = state.audio;
|
const { mute, chatNotify } = state.audio;
|
||||||
const { showGrid, showPixelNotify, autoZoomIn, compactPalette, isPotato } = state.gui;
|
const {
|
||||||
|
showGrid, showPixelNotify, autoZoomIn, compactPalette, isPotato,
|
||||||
|
} = state.gui;
|
||||||
const isMuted = mute;
|
const isMuted = mute;
|
||||||
const isGridShown = showGrid;
|
const isGridShown = showGrid;
|
||||||
const isPixelNotifyShown = showPixelNotify;
|
const isPixelNotifyShown = showPixelNotify;
|
||||||
return { isMuted, isGridShown, isPixelNotifyShown, autoZoomIn, compactPalette, chatNotify, isPotato };
|
return {
|
||||||
|
isMuted, isGridShown, isPixelNotifyShown, autoZoomIn, compactPalette, chatNotify, isPotato,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { validateEMail, validateName, validatePassword, parseAPIresponse } from '../utils/validation';
|
import {
|
||||||
|
validateEMail, validateName, validatePassword, parseAPIresponse,
|
||||||
|
} from '../utils/validation';
|
||||||
|
|
||||||
function validate(name, email, password, confirm_password) {
|
function validate(name, email, password, confirm_password) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
@ -64,7 +66,9 @@ class SignUpForm extends React.Component {
|
||||||
async handleSubmit(e) {
|
async handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { name, email, password, confirm_password, submitting } = this.state;
|
const {
|
||||||
|
name, email, password, confirm_password, submitting,
|
||||||
|
} = this.state;
|
||||||
if (submitting) return;
|
if (submitting) return;
|
||||||
|
|
||||||
const errors = validate(name, email, password, confirm_password);
|
const errors = validate(name, email, password, confirm_password);
|
||||||
|
@ -89,34 +93,34 @@ class SignUpForm extends React.Component {
|
||||||
const { errors } = this.state;
|
const { errors } = this.state;
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map(error => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.name}
|
value={this.state.name}
|
||||||
onChange={evt => this.setState({ name: evt.target.value })}
|
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.email}
|
value={this.state.email}
|
||||||
onChange={evt => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={evt => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.confirm_password}
|
value={this.state.confirm_password}
|
||||||
onChange={evt => this.setState({ confirm_password: evt.target.value })}
|
onChange={(evt) => this.setState({ confirm_password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Confirm Password"
|
placeholder="Confirm Password"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -19,14 +19,15 @@ const TotalRankings = ({ totalRanking }) => (
|
||||||
<th>Pixels Today</th>
|
<th>Pixels Today</th>
|
||||||
</tr>
|
</tr>
|
||||||
{
|
{
|
||||||
totalRanking.map(rank => (
|
totalRanking.map((rank) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{rank.ranking}</td>
|
<td>{rank.ranking}</td>
|
||||||
<td>{rank.name}</td>
|
<td>{rank.name}</td>
|
||||||
<td>{rank.totalPixels}</td>
|
<td>{rank.totalPixels}</td>
|
||||||
<td>{rank.dailyRanking}</td>
|
<td>{rank.dailyRanking}</td>
|
||||||
<td>{rank.dailyTotalPixels}</td>
|
<td>{rank.dailyTotalPixels}</td>
|
||||||
</tr>))
|
</tr>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -63,28 +63,30 @@ class UserArea extends React.Component {
|
||||||
> Log out</span> |
|
> Log out</span> |
|
||||||
<span
|
<span
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={evt => this.setState({
|
onClick={(evt) => this.setState({
|
||||||
change_name_extended: true,
|
change_name_extended: true,
|
||||||
change_mail_extended: false,
|
change_mail_extended: false,
|
||||||
change_passwd_extended: false,
|
change_passwd_extended: false,
|
||||||
delete_account_extended: false,
|
delete_account_extended: false,
|
||||||
})}
|
})}
|
||||||
> Change Username</span> |
|
> Change Username</span> |
|
||||||
{(this.props.mailreg) &&
|
{(this.props.mailreg)
|
||||||
|
&& (
|
||||||
<span>
|
<span>
|
||||||
<span
|
<span
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={evt => this.setState({
|
onClick={(evt) => this.setState({
|
||||||
change_name_extended: false,
|
change_name_extended: false,
|
||||||
change_mail_extended: true,
|
change_mail_extended: true,
|
||||||
change_passwd_extended: false,
|
change_passwd_extended: false,
|
||||||
delete_account_extended: false,
|
delete_account_extended: false,
|
||||||
})}
|
})}
|
||||||
> Change Mail</span> |
|
> Change Mail</span> |
|
||||||
</span>}
|
</span>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={evt => this.setState({
|
onClick={(evt) => this.setState({
|
||||||
change_name_extended: false,
|
change_name_extended: false,
|
||||||
change_mail_extended: false,
|
change_mail_extended: false,
|
||||||
change_passwd_extended: true,
|
change_passwd_extended: true,
|
||||||
|
@ -93,7 +95,7 @@ class UserArea extends React.Component {
|
||||||
> Change Password</span> |
|
> Change Password</span> |
|
||||||
<span
|
<span
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={evt => this.setState({
|
onClick={(evt) => this.setState({
|
||||||
change_name_extended: false,
|
change_name_extended: false,
|
||||||
change_mail_extended: false,
|
change_mail_extended: false,
|
||||||
change_passwd_extended: false,
|
change_passwd_extended: false,
|
||||||
|
@ -101,26 +103,34 @@ class UserArea extends React.Component {
|
||||||
})}
|
})}
|
||||||
> Delete Account</span> )
|
> Delete Account</span> )
|
||||||
</p>
|
</p>
|
||||||
{(this.state.change_passwd_extended) &&
|
{(this.state.change_passwd_extended)
|
||||||
|
&& (
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
mailreg={this.props.mailreg}
|
mailreg={this.props.mailreg}
|
||||||
done={() => { this.props.set_mailreg(true); this.setState({ change_passwd_extended: false }); }}
|
done={() => { this.props.set_mailreg(true); this.setState({ change_passwd_extended: false }); }}
|
||||||
cancel={() => { this.setState({ change_passwd_extended: false }); }}
|
cancel={() => { this.setState({ change_passwd_extended: false }); }}
|
||||||
/>}
|
/>
|
||||||
{(this.state.change_name_extended) &&
|
)}
|
||||||
|
{(this.state.change_name_extended)
|
||||||
|
&& (
|
||||||
<ChangeName
|
<ChangeName
|
||||||
set_name={this.props.set_name}
|
set_name={this.props.set_name}
|
||||||
done={() => { this.setState({ change_name_extended: false }); }}
|
done={() => { this.setState({ change_name_extended: false }); }}
|
||||||
/>}
|
/>
|
||||||
{(this.state.change_mail_extended) &&
|
)}
|
||||||
|
{(this.state.change_mail_extended)
|
||||||
|
&& (
|
||||||
<ChangeMail
|
<ChangeMail
|
||||||
done={() => { this.setState({ change_mail_extended: false }); }}
|
done={() => { this.setState({ change_mail_extended: false }); }}
|
||||||
/>}
|
/>
|
||||||
{(this.state.delete_account_extended) &&
|
)}
|
||||||
|
{(this.state.delete_account_extended)
|
||||||
|
&& (
|
||||||
<DeleteAccount
|
<DeleteAccount
|
||||||
set_name={this.props.set_name}
|
set_name={this.props.set_name}
|
||||||
done={() => { this.setState({ delete_account_extended: false }); }}
|
done={() => { this.setState({ delete_account_extended: false }); }}
|
||||||
/>}
|
/>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ import Modal from './Modal';
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../reducers';
|
||||||
|
|
||||||
|
|
||||||
import { showRegisterModal, showForgotPasswordModal, setName, setMailreg, receiveMe } from '../actions';
|
import {
|
||||||
|
showRegisterModal, showForgotPasswordModal, setName, setMailreg, receiveMe,
|
||||||
|
} from '../actions';
|
||||||
import LogInForm from './LogInForm';
|
import LogInForm from './LogInForm';
|
||||||
import Tabs from './Tabs';
|
import Tabs from './Tabs';
|
||||||
import UserArea from './UserArea';
|
import UserArea from './UserArea';
|
||||||
|
@ -63,11 +65,14 @@ const LogInArea = ({ register, forgot_password, me }) => (
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
const UserAreaModal = ({ name, register, forgot_password, doMe, logout, setName, setMailreg }) => (
|
const UserAreaModal = ({
|
||||||
|
name, register, forgot_password, doMe, logout, setName, setMailreg,
|
||||||
|
}) => (
|
||||||
<Modal title="User Area">
|
<Modal title="User Area">
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
{(name === null) ?
|
{(name === null)
|
||||||
<LogInArea register={register} forgot_password={forgot_password} me={doMe} /> :
|
? <LogInArea register={register} forgot_password={forgot_password} me={doMe} />
|
||||||
|
: (
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<div label="Profile">
|
<div label="Profile">
|
||||||
<UserArea
|
<UserArea
|
||||||
|
@ -79,7 +84,8 @@ const UserAreaModal = ({ name, register, forgot_password, doMe, logout, setName,
|
||||||
<div label="Ranking">
|
<div label="Ranking">
|
||||||
<Rankings />
|
<Rankings />
|
||||||
</div>
|
</div>
|
||||||
</Tabs>}
|
</Tabs>
|
||||||
|
)}
|
||||||
<p>Also join our Discord: <a href="./discord" target="_blank">pixelplanet.fun/discord</a></p>
|
<p>Also join our Discord: <a href="./discord" target="_blank">pixelplanet.fun/discord</a></p>
|
||||||
</p>
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -76,26 +76,28 @@ class UserMessages extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{(messages.includes('not_verified') && messages.splice(messages.indexOf('not_verified'), 1)) ?
|
{(messages.includes('not_verified') && messages.splice(messages.indexOf('not_verified'), 1))
|
||||||
|
? (
|
||||||
<p className="usermessages">
|
<p className="usermessages">
|
||||||
Please verify your mail address or your account could get deleted after a few days.
|
Please verify your mail address or your account could get deleted after a few days.
|
||||||
{(this.state.verify_answer) ?
|
{(this.state.verify_answer)
|
||||||
<span className="modallink">{this.state.verify_answer}</span> :
|
? <span className="modallink">{this.state.verify_answer}</span>
|
||||||
<span className="modallink" onClick={this.submit_resend_verify}>Click here to request a new verification mail.</span>
|
: <span className="modallink" onClick={this.submit_resend_verify}>Click here to request a new verification mail.</span>}
|
||||||
}
|
</p>
|
||||||
</p> : null
|
) : null}
|
||||||
}
|
{(messages.includes('not_mc_verified') && messages.splice(messages.indexOf('not_mc_verified'), 1))
|
||||||
{(messages.includes('not_mc_verified') && messages.splice(messages.indexOf('not_mc_verified'), 1)) ?
|
? (
|
||||||
<p className="usermessages">You requested to link your mc account {this.props.minecraftname}.
|
<p className="usermessages">You requested to link your mc account {this.props.minecraftname}.
|
||||||
{(this.state.link_answer) ?
|
{(this.state.link_answer)
|
||||||
<span className="modallink">{this.state.link_answer}</span> :
|
? <span className="modallink">{this.state.link_answer}</span>
|
||||||
|
: (
|
||||||
<span>
|
<span>
|
||||||
<span className="modallink" onClick={() => { this.submit_mc_link(true); }}>Accept</span> or <span className="modallink" onClick={() => { this.submit_mc_link(false); }}>Deny</span>.
|
<span className="modallink" onClick={() => { this.submit_mc_link(true); }}>Accept</span> or <span className="modallink" onClick={() => { this.submit_mc_link(false); }}>Deny</span>.
|
||||||
</span>
|
</span>
|
||||||
}
|
)}
|
||||||
</p> : null
|
</p>
|
||||||
}
|
) : null}
|
||||||
{messages.map(message => (
|
{messages.map((message) => (
|
||||||
<p className="usermessages" key={message} className="message">{message}</p>
|
<p className="usermessages" key={message} className="message">{message}</p>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,4 +2,3 @@
|
||||||
|
|
||||||
export type Index = number; // TODO integer >= 0
|
export type Index = number; // TODO integer >= 0
|
||||||
export type Cell = [number, number, number];
|
export type Cell = [number, number, number];
|
||||||
|
|
||||||
|
|
|
@ -152,4 +152,3 @@ export async function imagemask2Canvas(
|
||||||
}
|
}
|
||||||
logger.info('Imagemask loading done.');
|
logger.info('Imagemask loading done.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,12 @@ class Palette {
|
||||||
* @return index of color
|
* @return index of color
|
||||||
*/
|
*/
|
||||||
getIndexOfColor(r: number, g: number, b: number): ColorIndex {
|
getIndexOfColor(r: number, g: number, b: number): ColorIndex {
|
||||||
const rgb = this.rgb;
|
const { rgb } = this;
|
||||||
let i = rgb.length;
|
let i = rgb.length;
|
||||||
while (i >= 0) {
|
while (i >= 0) {
|
||||||
if (rgb[--i] === b &&
|
if (rgb[--i] === b
|
||||||
rgb[--i] === g &&
|
&& rgb[--i] === g
|
||||||
rgb[--i] === r
|
&& rgb[--i] === r
|
||||||
) {
|
) {
|
||||||
return (i / 3);
|
return (i / 3);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class Palette {
|
||||||
* @return ABRG Buffer
|
* @return ABRG Buffer
|
||||||
*/
|
*/
|
||||||
buffer2ABGR(chunkBuffer: Buffer): Uint32Array {
|
buffer2ABGR(chunkBuffer: Buffer): Uint32Array {
|
||||||
const length = chunkBuffer.length;
|
const { length } = chunkBuffer;
|
||||||
const colors = new Uint32Array(length);
|
const colors = new Uint32Array(length);
|
||||||
let value: number;
|
let value: number;
|
||||||
const buffer = chunkBuffer;
|
const buffer = chunkBuffer;
|
||||||
|
@ -94,7 +94,7 @@ class Palette {
|
||||||
* @return RGB Buffer
|
* @return RGB Buffer
|
||||||
*/
|
*/
|
||||||
buffer2RGB(chunkBuffer: Buffer): Uint8Array {
|
buffer2RGB(chunkBuffer: Buffer): Uint8Array {
|
||||||
const length = chunkBuffer.length;
|
const { length } = chunkBuffer;
|
||||||
const colors = new Uint8Array(length * 3);
|
const colors = new Uint8Array(length * 3);
|
||||||
let color: number;
|
let color: number;
|
||||||
let value: number;
|
let value: number;
|
||||||
|
@ -167,8 +167,7 @@ export const COLORS_RGB: Uint8Array = new Uint8Array([
|
||||||
25, 25, 115, // darker blue
|
25, 25, 115, // darker blue
|
||||||
207, 110, 228, // light violette
|
207, 110, 228, // light violette
|
||||||
130, 0, 128, // violette
|
130, 0, 128, // violette
|
||||||
],
|
]);
|
||||||
);
|
|
||||||
|
|
||||||
export const COLORS_AMOUNT = COLORS_RGB.length / 3;
|
export const COLORS_AMOUNT = COLORS_RGB.length / 3;
|
||||||
export const COLORS: Array<Color> = new Array(COLORS_AMOUNT);
|
export const COLORS: Array<Color> = new Array(COLORS_AMOUNT);
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Player {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.wait = null;
|
this.wait = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWait(wait) {
|
setWait(wait) {
|
||||||
this.wait = wait;
|
this.wait = wait;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,8 @@ export async function createZoomTileFromChunk(
|
||||||
canvasId: number,
|
canvasId: number,
|
||||||
canvasTileFolder: string,
|
canvasTileFolder: string,
|
||||||
palette: Palette,
|
palette: Palette,
|
||||||
cell: Cell): boolean {
|
cell: Cell,
|
||||||
|
): boolean {
|
||||||
const [x, y] = cell;
|
const [x, y] = cell;
|
||||||
const maxTiledZoom = getMaxTiledZoom(canvasSize);
|
const maxTiledZoom = getMaxTiledZoom(canvasSize);
|
||||||
const tileRGBBuffer = new Uint8Array(
|
const tileRGBBuffer = new Uint8Array(
|
||||||
|
@ -162,8 +163,7 @@ export async function createZoomTileFromChunk(
|
||||||
height: TILE_SIZE * TILE_ZOOM_LEVEL,
|
height: TILE_SIZE * TILE_ZOOM_LEVEL,
|
||||||
channels: 3,
|
channels: 3,
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.resize(TILE_SIZE)
|
.resize(TILE_SIZE)
|
||||||
.png({ options: { compressionLevel: 6 } })
|
.png({ options: { compressionLevel: 6 } })
|
||||||
.toFile(filename);
|
.toFile(filename);
|
||||||
|
@ -212,7 +212,8 @@ export async function createZoomedTile(
|
||||||
const filename = tileFileName(canvasTileFolder, [z, x, y]);
|
const filename = tileFileName(canvasTileFolder, [z, x, y]);
|
||||||
await sharp(
|
await sharp(
|
||||||
Buffer.from(
|
Buffer.from(
|
||||||
tileRGBBuffer.buffer), {
|
tileRGBBuffer.buffer,
|
||||||
|
), {
|
||||||
raw: {
|
raw: {
|
||||||
width: TILE_SIZE * TILE_ZOOM_LEVEL,
|
width: TILE_SIZE * TILE_ZOOM_LEVEL,
|
||||||
height: TILE_SIZE * TILE_ZOOM_LEVEL,
|
height: TILE_SIZE * TILE_ZOOM_LEVEL,
|
||||||
|
@ -255,8 +256,7 @@ export async function createEmptyTile(
|
||||||
height: TILE_SIZE,
|
height: TILE_SIZE,
|
||||||
channels: 3,
|
channels: 3,
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.png({ options: { compressionLevel: 6 } })
|
.png({ options: { compressionLevel: 6 } })
|
||||||
.toFile(filename);
|
.toFile(filename);
|
||||||
logger.info(`Tiling: Created empty tile at ${filename}`);
|
logger.info(`Tiling: Created empty tile at ${filename}`);
|
||||||
|
@ -422,4 +422,3 @@ export async function initializeTiles(
|
||||||
`Tiling: Elapsed Time: ${Math.round((Date.now() - startTime) / 1000)} for canvas${canvasId}`,
|
`Tiling: Elapsed Time: ${Math.round((Date.now() - startTime) / 1000)} for canvas${canvasId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ export const DISCORD_INVITE = process.env.DISCORD_INVITE || 'https://discordapp.
|
||||||
// Accounts
|
// Accounts
|
||||||
export const APISOCKET_KEY = process.env.APISOCKET_KEY || 'changethis';
|
export const APISOCKET_KEY = process.env.APISOCKET_KEY || 'changethis';
|
||||||
// Comma seperated list of user ids of Admins
|
// Comma seperated list of user ids of Admins
|
||||||
export const ADMIN_IDS = (process.env.ADMIN_IDS) ?
|
export const ADMIN_IDS = (process.env.ADMIN_IDS)
|
||||||
process.env.ADMIN_IDS.split(',').map(z => parseInt(z, 10)) : [];
|
? process.env.ADMIN_IDS.split(',').map((z) => parseInt(z, 10)) : [];
|
||||||
|
|
||||||
export const analytics = {
|
export const analytics = {
|
||||||
// https://analytics.google.com/
|
// https://analytics.google.com/
|
||||||
|
@ -83,4 +83,3 @@ export const RECAPTCHA_SITEKEY = process.env.RECAPTCHA_SITEKEY || false;
|
||||||
export const RECAPTCHA_TIME = parseInt(process.env.RECAPTCHA_TIME, 10) || 30;
|
export const RECAPTCHA_TIME = parseInt(process.env.RECAPTCHA_TIME, 10) || 30;
|
||||||
|
|
||||||
export const SESSION_SECRET = process.env.SESSION_SECRET || 'dummy';
|
export const SESSION_SECRET = process.env.SESSION_SECRET || 'dummy';
|
||||||
|
|
||||||
|
|
|
@ -88,4 +88,3 @@ export const MIN_COOLDOWN = 30 * SECOND; */
|
||||||
|
|
||||||
export const BLANK_COOLDOWN = 3 * SECOND;
|
export const BLANK_COOLDOWN = 3 * SECOND;
|
||||||
export const MIN_COOLDOWN = 15 * SECOND;
|
export const MIN_COOLDOWN = 15 * SECOND;
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,8 @@ async function draw(
|
||||||
|
|
||||||
const canvasMaxXY = canvas.size / 2;
|
const canvasMaxXY = canvas.size / 2;
|
||||||
const canvasMinXY = -canvasMaxXY;
|
const canvasMinXY = -canvasMaxXY;
|
||||||
if (x < canvasMinXY || y < canvasMinXY ||
|
if (x < canvasMinXY || y < canvasMinXY
|
||||||
x >= canvasMaxXY || y >= canvasMaxXY) {
|
|| x >= canvasMaxXY || y >= canvasMaxXY) {
|
||||||
return {
|
return {
|
||||||
error: 'Coordinates not withing canvas',
|
error: 'Coordinates not withing canvas',
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -11,9 +11,9 @@ function forceGC() {
|
||||||
if (global.gc) {
|
if (global.gc) {
|
||||||
global.gc();
|
global.gc();
|
||||||
} else {
|
} else {
|
||||||
logger.warn('Garbage collection unavailable. ' +
|
logger.warn('Garbage collection unavailable. '
|
||||||
'Pass --expose-gc when launching node to enable forced garbage ' +
|
+ 'Pass --expose-gc when launching node to enable forced garbage '
|
||||||
'collection.');
|
+ 'collection.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* @flow
|
* @flow
|
||||||
* */
|
* */
|
||||||
|
|
||||||
import fetch from '../utils/proxiedFetch.js';
|
|
||||||
import IP from 'ip';
|
import IP from 'ip';
|
||||||
|
import fetch from '../utils/proxiedFetch.js';
|
||||||
|
|
||||||
import redis from '../data/redis';
|
import redis from '../data/redis';
|
||||||
import { Blacklist, Whitelist } from '../data/models';
|
import { Blacklist, Whitelist } from '../data/models';
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// must use require for arguments
|
// must use require for arguments
|
||||||
|
import Sequelize from 'sequelize';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
import { HOUR, MINUTE } from './constants';
|
import { HOUR, MINUTE } from './constants';
|
||||||
import { HOSTURL } from './config';
|
import { HOSTURL } from './config';
|
||||||
import { DailyCron, HourlyCron } from '../utils/cron';
|
import { DailyCron, HourlyCron } from '../utils/cron';
|
||||||
|
|
||||||
import Sequelize from 'sequelize';
|
|
||||||
import RegUser from '../data/models/RegUser';
|
import RegUser from '../data/models/RegUser';
|
||||||
|
|
||||||
const sendmail = require('sendmail')({ silent: true });
|
const sendmail = require('sendmail')({ silent: true });
|
||||||
|
|
|
@ -11,7 +11,9 @@ import canvases from '../canvases.json';
|
||||||
export default async function getMe(user) {
|
export default async function getMe(user) {
|
||||||
const userdata = user.getUserData();
|
const userdata = user.getUserData();
|
||||||
// sanitize data
|
// sanitize data
|
||||||
const { name, mailVerified, minecraftname, mcVerified } = userdata;
|
const {
|
||||||
|
name, mailVerified, minecraftname, mcVerified,
|
||||||
|
} = userdata;
|
||||||
if (!name) userdata.name = null;
|
if (!name) userdata.name = null;
|
||||||
const messages = [];
|
const messages = [];
|
||||||
if (name && !mailVerified) {
|
if (name && !mailVerified) {
|
||||||
|
@ -30,4 +32,3 @@ export default async function getMe(user) {
|
||||||
|
|
||||||
return userdata;
|
return userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Model from '../data/sequelize';
|
||||||
import RegUser from '../data/models/RegUser';
|
import RegUser from '../data/models/RegUser';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
import { HOUR, MINUTE } from '../core/constants';
|
import { HOUR, MINUTE } from './constants';
|
||||||
import { DailyCron } from '../utils/cron';
|
import { DailyCron } from '../utils/cron';
|
||||||
|
|
||||||
class Ranks {
|
class Ranks {
|
||||||
|
|
|
@ -12,12 +12,16 @@ import canvases from '../canvases.json';
|
||||||
import Palette from './Palette';
|
import Palette from './Palette';
|
||||||
|
|
||||||
import { TILE_FOLDER } from './config';
|
import { TILE_FOLDER } from './config';
|
||||||
import { TILE_SIZE,
|
import {
|
||||||
TILE_ZOOM_LEVEL } from './constants';
|
TILE_SIZE,
|
||||||
import { createZoomTileFromChunk,
|
TILE_ZOOM_LEVEL,
|
||||||
|
} from './constants';
|
||||||
|
import {
|
||||||
|
createZoomTileFromChunk,
|
||||||
createZoomedTile,
|
createZoomedTile,
|
||||||
createTexture,
|
createTexture,
|
||||||
initializeTiles } from './Tile';
|
initializeTiles,
|
||||||
|
} from './Tile';
|
||||||
import { mod, getChunkOfPixel, getMaxTiledZoom } from './utils';
|
import { mod, getChunkOfPixel, getMaxTiledZoom } from './utils';
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +81,7 @@ class CanvasUpdater {
|
||||||
if (zoom === 0) {
|
if (zoom === 0) {
|
||||||
createTexture(this.id, this.canvas.size, this.canvasTileFolder, this.palette);
|
createTexture(this.id, this.canvas.size, this.canvasTileFolder, this.palette);
|
||||||
} else {
|
} else {
|
||||||
const [ucx, ucy] = [cx, cy].map(z => Math.floor(z / 4));
|
const [ucx, ucy] = [cx, cy].map((z) => Math.floor(z / 4));
|
||||||
const upperTile = ucx + ucy * (TILE_ZOOM_LEVEL ** (zoom - 1));
|
const upperTile = ucx + ucy * (TILE_ZOOM_LEVEL ** (zoom - 1));
|
||||||
const upperQueue = this.TileLoadingQueues[zoom - 1];
|
const upperQueue = this.TileLoadingQueues[zoom - 1];
|
||||||
if (~upperQueue.indexOf(upperTile)) return;
|
if (~upperQueue.indexOf(upperTile)) return;
|
||||||
|
@ -95,7 +99,7 @@ class CanvasUpdater {
|
||||||
const queue = this.TileLoadingQueues[Math.max(this.maxTiledZoom - 1, 0)];
|
const queue = this.TileLoadingQueues[Math.max(this.maxTiledZoom - 1, 0)];
|
||||||
if (typeof queue === 'undefined') return;
|
if (typeof queue === 'undefined') return;
|
||||||
|
|
||||||
const [cx, cy] = chunk.map(z => Math.floor(z / 4));
|
const [cx, cy] = chunk.map((z) => Math.floor(z / 4));
|
||||||
const chunkOffset = cx + cy * this.firstZoomtileWidth;
|
const chunkOffset = cx + cy * this.firstZoomtileWidth;
|
||||||
if (~queue.indexOf(chunkOffset)) return;
|
if (~queue.indexOf(chunkOffset)) return;
|
||||||
queue.push(chunkOffset);
|
queue.push(chunkOffset);
|
||||||
|
@ -166,4 +170,3 @@ export function startAllCanvasLoops() {
|
||||||
CanvasUpdaters[ids[i]] = updater;
|
CanvasUpdaters[ids[i]] = updater;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function mod(n: number, m: number): number {
|
||||||
export function sum(values: Array<number>): number {
|
export function sum(values: Array<number>): number {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
// TODO map reduce
|
// TODO map reduce
|
||||||
values.forEach(value => total += value);
|
values.forEach((value) => total += value);
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ export function clamp(n: number, min: number, max: number): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getChunkOfPixel(pixel: Cell, canvasSize: number = null): Cell {
|
export function getChunkOfPixel(pixel: Cell, canvasSize: number = null): Cell {
|
||||||
const target = pixel.map(x => Math.floor((x + (canvasSize / 2)) / TILE_SIZE));
|
const target = pixel.map((x) => Math.floor((x + (canvasSize / 2)) / TILE_SIZE));
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTileOfPixel(tileScale: number, pixel: Cell, canvasSize: number = null): Cell {
|
export function getTileOfPixel(tileScale: number, pixel: Cell, canvasSize: number = null): Cell {
|
||||||
const target = pixel.map(x => Math.floor((x + canvasSize / 2) / TILE_SIZE * tileScale));
|
const target = pixel.map((x) => Math.floor((x + canvasSize / 2) / TILE_SIZE * tileScale));
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ export function getPixelFromChunkOffset(
|
||||||
|
|
||||||
export function getCellInsideChunk(pixel: Cell): Cell {
|
export function getCellInsideChunk(pixel: Cell): Cell {
|
||||||
// TODO assert is positive!
|
// TODO assert is positive!
|
||||||
return pixel.map(x => mod(x, TILE_SIZE));
|
return pixel.map((x) => mod(x, TILE_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function screenToWorld(
|
export function screenToWorld(
|
||||||
|
@ -172,9 +172,9 @@ export function numberToString(num: number): string {
|
||||||
while (postfixNum < postfix.length) {
|
while (postfixNum < postfix.length) {
|
||||||
if (num < 10000) {
|
if (num < 10000) {
|
||||||
return `${Math.floor(num / 1000)}.${Math.floor((num % 1000) / 10)}${postfix[postfixNum]}`;
|
return `${Math.floor(num / 1000)}.${Math.floor((num % 1000) / 10)}${postfix[postfixNum]}`;
|
||||||
} else if (num < 100000) {
|
} if (num < 100000) {
|
||||||
return `${Math.floor(num / 1000)}.${Math.floor((num % 1000) / 100)}${postfix[postfixNum]}`;
|
return `${Math.floor(num / 1000)}.${Math.floor((num % 1000) / 100)}${postfix[postfixNum]}`;
|
||||||
} else if (num < 1000000) {
|
} if (num < 1000000) {
|
||||||
return Math.floor(num / 1000) + postfix[postfixNum];
|
return Math.floor(num / 1000) + postfix[postfixNum];
|
||||||
}
|
}
|
||||||
postfixNum += 1;
|
postfixNum += 1;
|
||||||
|
@ -186,9 +186,9 @@ export function numberToString(num: number): string {
|
||||||
export function numberToStringFull(num: number): string {
|
export function numberToStringFull(num: number): string {
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
return `${num} :-(`;
|
return `${num} :-(`;
|
||||||
} else if (num < 1000) {
|
} if (num < 1000) {
|
||||||
return num;
|
return num;
|
||||||
} else if (num < 1000000) {
|
} if (num < 1000000) {
|
||||||
return `${Math.floor(num / 1000)}.${(`00${num % 1000}`).slice(-3)}`;
|
return `${Math.floor(num / 1000)}.${(`00${num % 1000}`).slice(-3)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,7 @@ class RedisCanvas {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setChunk(i: number, j: number, chunk: Uint8Array,
|
static async setChunk(i: number, j: number, chunk: Uint8Array,
|
||||||
canvasId: number,
|
canvasId: number) {
|
||||||
) {
|
|
||||||
if (chunk.length !== TILE_SIZE * TILE_SIZE) {
|
if (chunk.length !== TILE_SIZE * TILE_SIZE) {
|
||||||
logger.error(`Tried to set chunk with invalid length ${chunk.length}!`);
|
logger.error(`Tried to set chunk with invalid length ${chunk.length}!`);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataType from 'sequelize';
|
import DataType from 'sequelize';
|
||||||
import Model from '../sequelize';
|
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
|
import Model from '../sequelize';
|
||||||
|
|
||||||
import { generateHash } from '../../utils/hash';
|
import { generateHash } from '../../utils/hash';
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
* @flow
|
* @flow
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
import Sequelize from 'sequelize';
|
||||||
import redis from '../redis';
|
import redis from '../redis';
|
||||||
import { randomDice } from '../../utils/random';
|
import { randomDice } from '../../utils/random';
|
||||||
import logger from '../../core/logger';
|
import logger from '../../core/logger';
|
||||||
import Sequelize from 'sequelize';
|
|
||||||
|
|
||||||
import Model from '../sequelize';
|
import Model from '../sequelize';
|
||||||
import RegUser from './RegUser';
|
import RegUser from './RegUser';
|
||||||
|
@ -58,7 +58,7 @@ class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
async incrementPixelcount(): Promise<boolean> {
|
async incrementPixelcount(): Promise<boolean> {
|
||||||
const id = this.id;
|
const { id } = this;
|
||||||
if (!id) return false;
|
if (!id) return false;
|
||||||
if (this.isAdmin()) return false;
|
if (this.isAdmin()) return false;
|
||||||
try {
|
try {
|
||||||
|
@ -75,7 +75,7 @@ class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTotalPixels(): Promise<number> {
|
async getTotalPixels(): Promise<number> {
|
||||||
const id = this.id;
|
const { id } = this;
|
||||||
if (!id) return 0;
|
if (!id) return 0;
|
||||||
if (this.isAdmin()) return 100000;
|
if (this.isAdmin()) return 100000;
|
||||||
if (this.regUser) {
|
if (this.regUser) {
|
||||||
|
@ -83,7 +83,9 @@ class User {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const userq = await Model.query('SELECT totalPixels FROM Users WHERE id = $1',
|
const userq = await Model.query('SELECT totalPixels FROM Users WHERE id = $1',
|
||||||
{ bind: [id], type: Sequelize.QueryTypes.SELECT, raw: true, plain: true });
|
{
|
||||||
|
bind: [id], type: Sequelize.QueryTypes.SELECT, raw: true, plain: true,
|
||||||
|
});
|
||||||
return userq.totalPixels;
|
return userq.totalPixels;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,4 +12,6 @@ function sync(...args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { sync };
|
export default { sync };
|
||||||
export { Whitelist, Blacklist, User, RegUser };
|
export {
|
||||||
|
Whitelist, Blacklist, User, RegUser,
|
||||||
|
};
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
import Sequelize from 'sequelize';
|
import Sequelize from 'sequelize';
|
||||||
|
|
||||||
import logging from '../core/logger';
|
import logging from '../core/logger';
|
||||||
import { MYSQL_HOST, MYSQL_DATABASE, MYSQL_USER, MYSQL_PW } from '../core/config';
|
import {
|
||||||
|
MYSQL_HOST, MYSQL_DATABASE, MYSQL_USER, MYSQL_PW,
|
||||||
|
} from '../core/config';
|
||||||
|
|
||||||
const sequelize = new Sequelize(MYSQL_DATABASE, MYSQL_USER, MYSQL_PW, {
|
const sequelize = new Sequelize(MYSQL_DATABASE, MYSQL_USER, MYSQL_PW, {
|
||||||
host: MYSQL_HOST,
|
host: MYSQL_HOST,
|
||||||
|
|
|
@ -16,10 +16,10 @@ function checkMaterial(object) {
|
||||||
|
|
||||||
function parseHashCoords() {
|
function parseHashCoords() {
|
||||||
try {
|
try {
|
||||||
const hash = window.location.hash;
|
const { hash } = window.location;
|
||||||
const array = hash.substring(1).split(',');
|
const array = hash.substring(1).split(',');
|
||||||
const ident = array.shift();
|
const ident = array.shift();
|
||||||
const [id, size, x, y] = array.map(z => parseInt(z, 10));
|
const [id, size, x, y] = array.map((z) => parseInt(z, 10));
|
||||||
if (!ident || isNaN(x) || isNaN(y) || isNaN(id) || isNaN(size)) {
|
if (!ident || isNaN(x) || isNaN(y) || isNaN(id) || isNaN(size)) {
|
||||||
throw new Error('NaN');
|
throw new Error('NaN');
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
loader.load('./assets3d/globe.glb', (glb) => {
|
loader.load('./assets3d/globe.glb', (glb) => {
|
||||||
scene.add(glb.scene);
|
scene.add(glb.scene);
|
||||||
const children = glb.scene.children;
|
const { children } = glb.scene;
|
||||||
for (let cnt = 0; cnt < children.length; cnt++) {
|
for (let cnt = 0; cnt < children.length; cnt++) {
|
||||||
if (checkMaterial(children[cnt])) {
|
if (checkMaterial(children[cnt])) {
|
||||||
object = children[cnt];
|
object = children[cnt];
|
||||||
|
@ -114,7 +114,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
rotateToCoords(canvasSize, object, [x, y]);
|
rotateToCoords(canvasSize, object, [x, y]);
|
||||||
controls = createControls();
|
controls = createControls();
|
||||||
render();
|
render();
|
||||||
document.getElementById('loading').style.display = "none";
|
document.getElementById('loading').style.display = 'none';
|
||||||
}, () => {
|
}, () => {
|
||||||
// console.log(`${xhr.loaded} loaded`);
|
// console.log(`${xhr.loaded} loaded`);
|
||||||
}, () => {
|
}, () => {
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
import type { Action } from '../actions/types';
|
import type { Action } from '../actions/types';
|
||||||
import type { Cell } from '../core/Cell';
|
import type { Cell } from '../core/Cell';
|
||||||
import Palette from '../core/Palette';
|
import Palette from '../core/Palette';
|
||||||
import { getMaxTiledZoom,
|
import {
|
||||||
|
getMaxTiledZoom,
|
||||||
getChunkOfPixel,
|
getChunkOfPixel,
|
||||||
getCellInsideChunk,
|
getCellInsideChunk,
|
||||||
clamp,
|
clamp,
|
||||||
|
@ -51,7 +52,7 @@ function getGivenCoords() {
|
||||||
* @return view, viewscale and scale for state
|
* @return view, viewscale and scale for state
|
||||||
*/
|
*/
|
||||||
function getViewFromURL(canvases: Object) {
|
function getViewFromURL(canvases: Object) {
|
||||||
const hash: string = window.location.hash;
|
const { hash } = window.location;
|
||||||
try {
|
try {
|
||||||
const almost = hash.substring(1)
|
const almost = hash.substring(1)
|
||||||
.split(',');
|
.split(',');
|
||||||
|
@ -59,8 +60,8 @@ function getViewFromURL(canvases: Object) {
|
||||||
const canvasIdent = almost[0];
|
const canvasIdent = almost[0];
|
||||||
// will be null if not in DEFAULT_CANVASES
|
// will be null if not in DEFAULT_CANVASES
|
||||||
const canvasId = getIdFromObject(canvases, almost[0]);
|
const canvasId = getIdFromObject(canvases, almost[0]);
|
||||||
const colors = (canvasId !== null) ?
|
const colors = (canvasId !== null)
|
||||||
canvases[canvasId].colors : canvases[DEFAULT_CANVAS_ID].colors;
|
? canvases[canvasId].colors : canvases[DEFAULT_CANVAS_ID].colors;
|
||||||
const canvasSize = (canvasId !== null) ? canvases[canvasId].size : 1024;
|
const canvasSize = (canvasId !== null) ? canvases[canvasId].size : 1024;
|
||||||
|
|
||||||
const x = parseInt(almost[1], 10);
|
const x = parseInt(almost[1], 10);
|
||||||
|
@ -115,7 +116,9 @@ export default function gui(
|
||||||
): CanvasState {
|
): CanvasState {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'PLACE_PIXEL': {
|
case 'PLACE_PIXEL': {
|
||||||
const { chunks, canvasMaxTiledZoom, palette, canvasSize } = state;
|
const {
|
||||||
|
chunks, canvasMaxTiledZoom, palette, canvasSize,
|
||||||
|
} = state;
|
||||||
const { coordinates, color } = action;
|
const { coordinates, color } = action;
|
||||||
|
|
||||||
const [cx, cy] = getChunkOfPixel(coordinates, canvasSize);
|
const [cx, cy] = getChunkOfPixel(coordinates, canvasSize);
|
||||||
|
@ -159,7 +162,7 @@ export default function gui(
|
||||||
}
|
}
|
||||||
const canvasMinXY = -canvasSize / 2;
|
const canvasMinXY = -canvasSize / 2;
|
||||||
const canvasMaxXY = canvasSize / 2 - 1;
|
const canvasMaxXY = canvasSize / 2 - 1;
|
||||||
view = [hx, hy].map(z => clamp(z, canvasMinXY, canvasMaxXY));
|
view = [hx, hy].map((z) => clamp(z, canvasMinXY, canvasMaxXY));
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
view,
|
view,
|
||||||
|
@ -173,7 +176,7 @@ export default function gui(
|
||||||
const { canvasSize } = state;
|
const { canvasSize } = state;
|
||||||
const canvasMinXY = -canvasSize / 2;
|
const canvasMinXY = -canvasSize / 2;
|
||||||
const canvasMaxXY = canvasSize / 2 - 1;
|
const canvasMaxXY = canvasSize / 2 - 1;
|
||||||
const newview = view.map(z => clamp(z, canvasMinXY, canvasMaxXY));
|
const newview = view.map((z) => clamp(z, canvasMinXY, canvasMaxXY));
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
view: newview,
|
view: newview,
|
||||||
|
@ -209,12 +212,14 @@ export default function gui(
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'REQUEST_BIG_CHUNK': {
|
case 'REQUEST_BIG_CHUNK': {
|
||||||
const { palette, chunks, fetchs, requested } = state;
|
const {
|
||||||
|
palette, chunks, fetchs, requested,
|
||||||
|
} = state;
|
||||||
const { center } = action;
|
const { center } = action;
|
||||||
|
|
||||||
const chunkRGB = new ChunkRGB(palette, center);
|
const chunkRGB = new ChunkRGB(palette, center);
|
||||||
// chunkRGB.preLoad(chunks);
|
// chunkRGB.preLoad(chunks);
|
||||||
const key = chunkRGB.key;
|
const { key } = chunkRGB;
|
||||||
chunks.set(key, chunkRGB);
|
chunks.set(key, chunkRGB);
|
||||||
|
|
||||||
requested.add(key);
|
requested.add(key);
|
||||||
|
@ -281,7 +286,9 @@ export default function gui(
|
||||||
const { chunks, canvasMaxTiledZoom } = state;
|
const { chunks, canvasMaxTiledZoom } = state;
|
||||||
// i, j: Coordinates of chunk
|
// i, j: Coordinates of chunk
|
||||||
// offset: Offset of pixel within said chunk
|
// offset: Offset of pixel within said chunk
|
||||||
const { i, j, offset, color } = action;
|
const {
|
||||||
|
i, j, offset, color,
|
||||||
|
} = action;
|
||||||
|
|
||||||
const key = ChunkRGB.getKey(canvasMaxTiledZoom, i, j);
|
const key = ChunkRGB.getKey(canvasMaxTiledZoom, i, j);
|
||||||
const chunk = chunks.get(key);
|
const chunk = chunks.get(key);
|
||||||
|
|
|
@ -40,7 +40,7 @@ router.use(session);
|
||||||
* (cut IPv6 to subnet to prevent abuse)
|
* (cut IPv6 to subnet to prevent abuse)
|
||||||
*/
|
*/
|
||||||
router.use(async (req, res, next) => {
|
router.use(async (req, res, next) => {
|
||||||
const session = req.session;
|
const { session } = req;
|
||||||
const id = (session.passport && session.passport.user) ? session.passport.user : null;
|
const id = (session.passport && session.passport.user) ? session.passport.user : null;
|
||||||
const ip = await getIPFromRequest(req);
|
const ip = await getIPFromRequest(req);
|
||||||
const trueIp = ip || '0.0.0.1';
|
const trueIp = ip || '0.0.0.1';
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default async (req: Request, res: Response) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const minecraftid = user.regUser.minecraftid;
|
const { minecraftid } = user.regUser;
|
||||||
if (!minecraftid) {
|
if (!minecraftid) {
|
||||||
res.status(400);
|
res.status(400);
|
||||||
res.json({
|
res.json({
|
||||||
|
|
|
@ -33,8 +33,7 @@ router.use('/',
|
||||||
total: 24,
|
total: 24,
|
||||||
expire: 5 * MINUTE,
|
expire: 5 * MINUTE,
|
||||||
skipHeaders: true,
|
skipHeaders: true,
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -181,7 +181,9 @@ class APISocketServer extends EventEmitter {
|
||||||
}
|
}
|
||||||
const user = this.mc.minecraftid2User(minecraftid);
|
const user = this.mc.minecraftid2User(minecraftid);
|
||||||
user.ip = ip;
|
user.ip = ip;
|
||||||
const { error, success, waitSeconds, coolDownSeconds } = await drawUnsafe(user, 0, x, y, clr);
|
const {
|
||||||
|
error, success, waitSeconds, coolDownSeconds,
|
||||||
|
} = await drawUnsafe(user, 0, x, y, clr);
|
||||||
ws.send(JSON.stringify([
|
ws.send(JSON.stringify([
|
||||||
'retpxl',
|
'retpxl',
|
||||||
(minecraftid) || ip,
|
(minecraftid) || ip,
|
||||||
|
|
|
@ -175,8 +175,8 @@ class ProtocolClient extends EventEmitter {
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
// reconnect in 1s if last connect was longer than 7s ago, else 5s
|
// reconnect in 1s if last connect was longer than 7s ago, else 5s
|
||||||
const timeout = (this.timeConnected < Date.now() - 7000) ? 1000 : 5000;
|
const timeout = (this.timeConnected < Date.now() - 7000) ? 1000 : 5000;
|
||||||
console.warn('Socket is closed. ' +
|
console.warn('Socket is closed. '
|
||||||
`Reconnect will be attempted in ${timeout} ms.`, e.reason);
|
+ `Reconnect will be attempted in ${timeout} ms.`, e.reason);
|
||||||
|
|
||||||
setTimeout(() => this.connect(), 5000);
|
setTimeout(() => this.connect(), 5000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ class SocketServer extends EventEmitter {
|
||||||
break;
|
break;
|
||||||
case RegisterMultipleChunks.OP_CODE:
|
case RegisterMultipleChunks.OP_CODE:
|
||||||
this.deleteAllChunks(ws);
|
this.deleteAllChunks(ws);
|
||||||
const length = buffer.length;
|
const { length } = buffer;
|
||||||
let posu = 2;
|
let posu = 2;
|
||||||
while (posu < length) {
|
while (posu < length) {
|
||||||
const chunkid = buffer[posu++] | buffer[posu++] << 8;
|
const chunkid = buffer[posu++] | buffer[posu++] << 8;
|
||||||
|
|
|
@ -25,7 +25,9 @@ export default {
|
||||||
const j = data.getInt16(3);
|
const j = data.getInt16(3);
|
||||||
const offset = data.getUint16(5);
|
const offset = data.getUint16(5);
|
||||||
const color = data.getUint8(7);
|
const color = data.getUint8(7);
|
||||||
return { i, j, offset, color };
|
return {
|
||||||
|
i, j, offset, color,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
dehydrate(i, j, offset, color): Buffer {
|
dehydrate(i, j, offset, color): Buffer {
|
||||||
// SERVER
|
// SERVER
|
||||||
|
|
|
@ -19,7 +19,7 @@ router.use(session);
|
||||||
* (cut IPv6 to subnet to prevent abuse)
|
* (cut IPv6 to subnet to prevent abuse)
|
||||||
*/
|
*/
|
||||||
router.use(async (req, res, next) => {
|
router.use(async (req, res, next) => {
|
||||||
const session = req.session;
|
const { session } = req;
|
||||||
const ip = await getIPFromRequest(req);
|
const ip = await getIPFromRequest(req);
|
||||||
const trueIp = ip || '0.0.0.1';
|
const trueIp = ip || '0.0.0.1';
|
||||||
req.trueIp = trueIp;
|
req.trueIp = trueIp;
|
||||||
|
|
|
@ -111,7 +111,7 @@ startOnlineCounterBroadcast();
|
||||||
* Get hooked up to httpServer and routes to the right socket
|
* Get hooked up to httpServer and routes to the right socket
|
||||||
*/
|
*/
|
||||||
export function wsupgrade(request, socket, head) {
|
export function wsupgrade(request, socket, head) {
|
||||||
const pathname = url.parse(request.url).pathname;
|
const { pathname } = url.parse(request.url);
|
||||||
|
|
||||||
if (pathname === '/ws') {
|
if (pathname === '/ws') {
|
||||||
usersocket.wss.handleUpgrade(request, socket, head, (ws) => {
|
usersocket.wss.handleUpgrade(request, socket, head, (ws) => {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
import { playAd } from '../ui/ads';
|
import { playAd } from '../ui/ads';
|
||||||
|
|
||||||
|
|
||||||
export default store => next => (action) => {
|
export default (store) => (next) => (action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'PLACE_PIXEL': {
|
case 'PLACE_PIXEL': {
|
||||||
// wait 1 second
|
// wait 1 second
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
import track from './track';
|
import track from './track';
|
||||||
|
|
||||||
export default store => next => (action) => {
|
export default (store) => (next) => (action) => {
|
||||||
track(action);
|
track(action);
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
* DEALINGS IN THE SOFTWARE
|
* DEALINGS IN THE SOFTWARE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default store => next => action =>
|
export default (store) => (next) => (action) => (Array.isArray(action)
|
||||||
(Array.isArray(action)
|
|
||||||
? action.map(next)
|
? action.map(next)
|
||||||
: next(action));
|
: next(action));
|
||||||
|
|
|
@ -10,7 +10,7 @@ const COLORS_AMOUNT = 32;
|
||||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||||
const context = new AudioContext();
|
const context = new AudioContext();
|
||||||
|
|
||||||
export default store => next => (action) => {
|
export default (store) => (next) => (action) => {
|
||||||
const { mute, chatNotify } = store.getState().audio;
|
const { mute, chatNotify } = store.getState().audio;
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
@ -85,7 +85,7 @@ export default store => next => (action) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'PLACE_PIXEL' : {
|
case 'PLACE_PIXEL': {
|
||||||
if (mute) break;
|
if (mute) break;
|
||||||
const { color } = action;
|
const { color } = action;
|
||||||
const clrFreq = 100 + Math.log(color / COLORS_AMOUNT + 1) * 300;
|
const clrFreq = 100 + Math.log(color / COLORS_AMOUNT + 1) * 300;
|
||||||
|
@ -107,7 +107,7 @@ export default store => next => (action) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'COOLDOWN_END' : {
|
case 'COOLDOWN_END': {
|
||||||
if (mute) break;
|
if (mute) break;
|
||||||
const oscillatorNode = context.createOscillator();
|
const oscillatorNode = context.createOscillator();
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
|
|
|
@ -14,7 +14,7 @@ function onDenied() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default store => next => (action) => {
|
export default (store) => (next) => (action) => {
|
||||||
if (!Push.isSupported) return next(action);
|
if (!Push.isSupported) return next(action);
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
|
@ -25,7 +25,6 @@ function warn(error) {
|
||||||
throw error; // To let the caller handle the rejection
|
throw error; // To let the caller handle the rejection
|
||||||
}
|
}
|
||||||
|
|
||||||
export default store => next => action =>
|
export default (store) => (next) => (action) => (typeof action.then === 'function'
|
||||||
(typeof action.then === 'function'
|
|
||||||
? Promise.resolve(action).then(next, warn)
|
? Promise.resolve(action).then(next, warn)
|
||||||
: next(action));
|
: next(action));
|
||||||
|
|
|
@ -12,7 +12,7 @@ const TITLE = 'PixelPlanet.fun';
|
||||||
|
|
||||||
let lastTitle = null;
|
let lastTitle = null;
|
||||||
|
|
||||||
export default store => next => (action) => {
|
export default (store) => (next) => (action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'COOLDOWN_SET': {
|
case 'COOLDOWN_SET': {
|
||||||
const { coolDown } = store.getState().user;
|
const { coolDown } = store.getState().user;
|
||||||
|
@ -34,4 +34,3 @@ export default store => next => (action) => {
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class PixelNotify {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const [sx, sy] = worldToScreen(state, $viewport, [x, y])
|
const [sx, sy] = worldToScreen(state, $viewport, [x, y])
|
||||||
.map(x => x + this.scale / 2);
|
.map((x) => x + this.scale / 2);
|
||||||
|
|
||||||
const notRadius = timePasseded / PixelNotify.NOTIFICATION_TIME * this.notificationRadius;
|
const notRadius = timePasseded / PixelNotify.NOTIFICATION_TIME * this.notificationRadius;
|
||||||
const circleScale = notRadius / 100;
|
const circleScale = notRadius / 100;
|
||||||
|
|
|
@ -95,7 +95,7 @@ class Renderer {
|
||||||
const [x, y] = getPixelFromChunkOffset(i, j, offset, this.canvasSize);
|
const [x, y] = getPixelFromChunkOffset(i, j, offset, this.canvasSize);
|
||||||
|
|
||||||
const [canX, canY] = this.centerChunk
|
const [canX, canY] = this.centerChunk
|
||||||
.map(z => (z + 0.5) * TILE_SIZE - this.canvasSize / 2);
|
.map((z) => (z + 0.5) * TILE_SIZE - this.canvasSize / 2);
|
||||||
const px = ((x - canX) * scale) + (CANVAS_WIDTH / 2);
|
const px = ((x - canX) * scale) + (CANVAS_WIDTH / 2);
|
||||||
const py = ((y - canY) * scale) + (CANVAS_HEIGHT / 2);
|
const py = ((y - canY) * scale) + (CANVAS_HEIGHT / 2);
|
||||||
// if not part of our current canvas, do not render
|
// if not part of our current canvas, do not render
|
||||||
|
@ -118,10 +118,8 @@ class Renderer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const { width, height } = this.viewport;
|
const { width, height } = this.viewport;
|
||||||
const CHUNK_RENDER_RADIUS_X =
|
const CHUNK_RENDER_RADIUS_X = Math.ceil(width / TILE_SIZE / 2 / this.relScale);
|
||||||
Math.ceil(width / TILE_SIZE / 2 / this.relScale);
|
const CHUNK_RENDER_RADIUS_Y = Math.ceil(height / TILE_SIZE / 2 / this.relScale);
|
||||||
const CHUNK_RENDER_RADIUS_Y =
|
|
||||||
Math.ceil(height / TILE_SIZE / 2 / this.relScale);
|
|
||||||
const [xc, yc] = this.centerChunk;
|
const [xc, yc] = this.centerChunk;
|
||||||
if (Math.abs(cx - xc)
|
if (Math.abs(cx - xc)
|
||||||
<= CHUNK_RENDER_RADIUS_X && Math.abs(cy - yc)
|
<= CHUNK_RENDER_RADIUS_X && Math.abs(cy - yc)
|
||||||
|
@ -141,8 +139,10 @@ class Renderer {
|
||||||
const context = this.canvas.getContext('2d');
|
const context = this.canvas.getContext('2d');
|
||||||
if (!context) return;
|
if (!context) return;
|
||||||
|
|
||||||
const { centerChunk: chunkPosition, scale, tiledScale, tiledZoom } = this;
|
const {
|
||||||
let relScale = this.relScale;
|
centerChunk: chunkPosition, scale, tiledScale, tiledZoom,
|
||||||
|
} = this;
|
||||||
|
let { relScale } = this;
|
||||||
// clear rect is just needed for Google Chrome, else it would flash regularly
|
// clear rect is just needed for Google Chrome, else it would flash regularly
|
||||||
context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ class Renderer {
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const viewport = this.viewport;
|
const { viewport } = this;
|
||||||
const state: State = store.getState();
|
const state: State = store.getState();
|
||||||
const {
|
const {
|
||||||
showGrid,
|
showGrid,
|
||||||
|
@ -296,14 +296,14 @@ class Renderer {
|
||||||
// note: this.hover is used to, to render without the placeholder one last time when cursor leaves window
|
// note: this.hover is used to, to render without the placeholder one last time when cursor leaves window
|
||||||
} else if (
|
} else if (
|
||||||
// no full rerender
|
// no full rerender
|
||||||
!doRenderCanvas &&
|
!doRenderCanvas
|
||||||
// no render placeholder under cursor
|
// no render placeholder under cursor
|
||||||
!doRenderPlaceholder &&
|
&& !doRenderPlaceholder
|
||||||
!doRenderPotatoPlaceholder &&
|
&& !doRenderPotatoPlaceholder
|
||||||
// no pixelnotification
|
// no pixelnotification
|
||||||
!doRenderPixelnotify &&
|
&& !doRenderPixelnotify
|
||||||
// no forced just-viewscale render (i.e. when just a pixel got set)
|
// no forced just-viewscale render (i.e. when just a pixel got set)
|
||||||
!this.forceNextSubrender
|
&& !this.forceNextSubrender
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -332,14 +332,12 @@ class Renderer {
|
||||||
viewportCtx.scale(viewscale, viewscale);
|
viewportCtx.scale(viewscale, viewscale);
|
||||||
viewportCtx.drawImage(this.canvas,
|
viewportCtx.drawImage(this.canvas,
|
||||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
||||||
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y));
|
||||||
);
|
|
||||||
viewportCtx.restore();
|
viewportCtx.restore();
|
||||||
} else {
|
} else {
|
||||||
viewportCtx.drawImage(this.canvas,
|
viewportCtx.drawImage(this.canvas,
|
||||||
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - x) * viewscale),
|
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - x) * viewscale),
|
||||||
Math.floor(height / 2 - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - y) * viewscale),
|
Math.floor(height / 2 - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - y) * viewscale));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showGrid && viewscale >= 8) renderGrid(state, viewport, viewscale);
|
if (showGrid && viewscale >= 8) renderGrid(state, viewport, viewscale);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
import keycode from 'keycode';
|
import keycode from 'keycode';
|
||||||
|
|
||||||
import store from '../ui/store';
|
import store from './store';
|
||||||
import {
|
import {
|
||||||
toggleGrid,
|
toggleGrid,
|
||||||
togglePixelNotify,
|
togglePixelNotify,
|
||||||
|
|
|
@ -101,4 +101,3 @@ export function renderGrid(
|
||||||
|
|
||||||
viewportCtx.globalAlpha = 1;
|
viewportCtx.globalAlpha = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ function isCloudflareIp(testIpString: string): boolean {
|
||||||
if (!testIpString) return false;
|
if (!testIpString) return false;
|
||||||
const testIp = intoAddress(testIpString);
|
const testIp = intoAddress(testIpString);
|
||||||
if (!testIp) return false;
|
if (!testIp) return false;
|
||||||
return cloudflareIps.some(cf => testIp.isInSubnet(cf));
|
return cloudflareIps.some((cf) => testIp.isInSubnet(cf));
|
||||||
}
|
}
|
||||||
|
|
||||||
export default isCloudflareIp;
|
export default isCloudflareIp;
|
||||||
|
|
|
@ -30,7 +30,7 @@ export async function getIPFromRequest(req): ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const forwardedFor = headers['x-forwarded-for'];
|
const forwardedFor = headers['x-forwarded-for'];
|
||||||
const ipList = forwardedFor.split(',').map(str => str.trim());
|
const ipList = forwardedFor.split(',').map((str) => str.trim());
|
||||||
|
|
||||||
let ip = ipList.pop();
|
let ip = ipList.pop();
|
||||||
while (isTrustedProxy(ip) && ipList.length) {
|
while (isTrustedProxy(ip) && ipList.length) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ export function validateEMail(email) {
|
||||||
if (email.length < 5) return 'Email should be at least 5 characters long.';
|
if (email.length < 5) return 'Email should be at least 5 characters long.';
|
||||||
if (email.length > 40) return "Email can't be longer than 40 characters.";
|
if (email.length > 40) return "Email can't be longer than 40 characters.";
|
||||||
if (email.indexOf('.') === -1) return 'Email should at least contain a dot';
|
if (email.indexOf('.') === -1) return 'Email should at least contain a dot';
|
||||||
if (email.split('').filter(x => x === '@').length !== 1) {
|
if (email.split('').filter((x) => x === '@').length !== 1) {
|
||||||
return 'Email should contain a @';
|
return 'Email should contain a @';
|
||||||
}
|
}
|
||||||
if (!mailTester.test(email)) return 'Your Email looks shady';
|
if (!mailTester.test(email)) return 'Your Email looks shady';
|
||||||
|
@ -21,12 +21,12 @@ export function validateName(name) {
|
||||||
if (!name) return "Name can't be empty.";
|
if (!name) return "Name can't be empty.";
|
||||||
if (name.length < 4) return 'Name must be at least 4 characters long';
|
if (name.length < 4) return 'Name must be at least 4 characters long';
|
||||||
if (name.length > 26) return 'Name must be shorter than 26 characters';
|
if (name.length > 26) return 'Name must be shorter than 26 characters';
|
||||||
if (name.indexOf('@') !== -1 ||
|
if (name.indexOf('@') !== -1
|
||||||
name.indexOf('/') !== -1 ||
|
|| name.indexOf('/') !== -1
|
||||||
name.indexOf('\\') !== -1 ||
|
|| name.indexOf('\\') !== -1
|
||||||
name.indexOf('>') !== -1 ||
|
|| name.indexOf('>') !== -1
|
||||||
name.indexOf('<') !== -1 ||
|
|| name.indexOf('<') !== -1
|
||||||
name.indexOf('#') !== -1) {
|
|| name.indexOf('#') !== -1) {
|
||||||
return 'Name contains invalid character like @, /, \\ or #';
|
return 'Name contains invalid character like @, /, \\ or #';
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -62,13 +62,15 @@ app.use('/tiles', tiles);
|
||||||
/* level from -1 (default, 6) to 0 (no) from 1 (fastest) to 9 (best)
|
/* level from -1 (default, 6) to 0 (no) from 1 (fastest) to 9 (best)
|
||||||
* Set custon filter to make sure that .bmp files get compressed
|
* Set custon filter to make sure that .bmp files get compressed
|
||||||
*/
|
*/
|
||||||
app.use(compression({ level: 3,
|
app.use(compression({
|
||||||
|
level: 3,
|
||||||
filter: (req, res) => {
|
filter: (req, res) => {
|
||||||
if (res.getHeader('Content-Type') === 'application/octet-stream') {
|
if (res.getHeader('Content-Type') === 'application/octet-stream') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return compression.filter(req, res);
|
return compression.filter(req, res);
|
||||||
} }));
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -161,7 +163,7 @@ app.get('/', async (req, res) => {
|
||||||
//
|
//
|
||||||
// ip config
|
// ip config
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const promise = models.sync().catch(err => logger.error(err.stack));
|
const promise = models.sync().catch((err) => logger.error(err.stack));
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
server.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
const address = server.address();
|
const address = server.address();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user