feat: handle reconnection
This commit is contained in:
parent
16bba31786
commit
2bcb541c99
|
@ -142,6 +142,15 @@ const AugmentedParser = augmentParserWithThroughput(SocketIoParser);
|
|||
const socket = createClient(window.location.href, {
|
||||
parser: AugmentedParser,
|
||||
});
|
||||
let isConnected = false;
|
||||
socket.on('connect', () => {
|
||||
room.layers.destroy();
|
||||
selfEntity = undefined;
|
||||
isConnected = true;
|
||||
});
|
||||
socket.on('disconnect', () => {
|
||||
isConnected = false;
|
||||
});
|
||||
// Mouse/touch movement.
|
||||
const pointerMovementHandle = setInterval(() => {
|
||||
do {
|
||||
|
@ -172,6 +181,9 @@ const pointerMovementHandle = setInterval(() => {
|
|||
}, 1000 / 15);
|
||||
// Input messages.
|
||||
const inputHandle = setInterval(() => {
|
||||
if (!isConnected) {
|
||||
return;
|
||||
}
|
||||
if (actionState !== actionRegistry.state) {
|
||||
actionState = actionRegistry.state;
|
||||
socket.send(InputPacket.fromState(actionState));
|
||||
|
@ -185,6 +197,9 @@ renderTicker.on('tick', () => {
|
|||
});
|
||||
let lastTime = performance.now();
|
||||
const predictionHandle = setInterval(() => {
|
||||
if (!isConnected) {
|
||||
return;
|
||||
}
|
||||
const now = performance.now();
|
||||
const elapsed = (now - lastTime) / 1000;
|
||||
lastTime = now;
|
||||
|
@ -254,6 +269,9 @@ function applyStageLighting() {
|
|||
}
|
||||
// Render.
|
||||
function render() {
|
||||
if (!isConnected) {
|
||||
return;
|
||||
}
|
||||
stage.tick();
|
||||
if (!mayRender) {
|
||||
return false;
|
||||
|
@ -266,6 +284,7 @@ function render() {
|
|||
const renderHandle = setAnimation(render);
|
||||
// UI.
|
||||
const UiComponent = <Ui
|
||||
socket={socket}
|
||||
worldTime={worldTime}
|
||||
/>;
|
||||
ReactDOM.render(UiComponent, stage.ui);
|
||||
|
|
78
client/ui/connection-status.js
Normal file
78
client/ui/connection-status.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
// 3rd party.
|
||||
import classnames from 'classnames';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
// 2nd party.
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(`
|
||||
.connection-status {
|
||||
display: none;
|
||||
}
|
||||
.connection-status.interrupted {
|
||||
background-color: rgba(0, 0, 0, .75);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.connection-status.interrupted .message {
|
||||
color: white;
|
||||
font-family: mono;
|
||||
font-size: 0.7em;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.connection-status.interrupted .message .dots {
|
||||
color: rgb(150, 150, 150);
|
||||
font-size: 0.5em;
|
||||
}
|
||||
`),
|
||||
);
|
||||
|
||||
const ConnectionStatusComponent = ({socket}) => {
|
||||
// Start true even if not really connected to prevent initial "interrupted"
|
||||
// state.
|
||||
const [isConnected, setIsConnected] = useState(true);
|
||||
const [dots, setDots] = useState(0);
|
||||
// Juggle connected state.
|
||||
useEffect(() => {
|
||||
const onConnect = () => {
|
||||
setIsConnected(true);
|
||||
};
|
||||
socket.on('connect', onConnect);
|
||||
const onDisconnect = () => {
|
||||
setIsConnected(false);
|
||||
};
|
||||
socket.on('disconnect', onDisconnect);
|
||||
return () => {
|
||||
socket.off('connect', onConnect);
|
||||
socket.off('disconnect', onDisconnect);
|
||||
};
|
||||
}, []);
|
||||
// Make the dots dance.
|
||||
useEffect(() => {
|
||||
if (isConnected) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
setDots((dots + 1) % 39);
|
||||
}, 50);
|
||||
}, [dots, isConnected]);
|
||||
const renderedDots = Array(dots + 1).fill('.').join('');
|
||||
return <div className={classnames(
|
||||
'connection-status',
|
||||
!isConnected ? 'interrupted' : '',
|
||||
'unselectable',
|
||||
)}>
|
||||
<div className="message">
|
||||
<p>:[ Connection interrupted ]:</p>
|
||||
<p className="dots">{renderedDots}</p>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
export default decorate(ConnectionStatusComponent);
|
|
@ -2,11 +2,13 @@
|
|||
import React from 'react';
|
||||
import {hot} from 'react-hot-loader/root';
|
||||
// 1st party.
|
||||
import ConnectionStatus from './connection-status';
|
||||
import WorldTime from './world-time';
|
||||
|
||||
const Ui = ({worldTime}) => {
|
||||
const Ui = ({socket, worldTime}) => {
|
||||
return <React.Fragment>
|
||||
<WorldTime worldTime={worldTime} />
|
||||
<ConnectionStatus socket={socket} />
|
||||
</React.Fragment>;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user