2019-03-20 15:28:18 -05:00
|
|
|
// Node.
|
|
|
|
import {performance} from 'perf_hooks';
|
|
|
|
// 3rd party.
|
|
|
|
import immutablediff from 'immutablediff';
|
|
|
|
// 2nd party.
|
2019-04-07 20:04:34 -05:00
|
|
|
import {Synchronizer} from '@avocado/state';
|
2019-03-27 15:51:58 -05:00
|
|
|
// 1st party.
|
2019-04-04 07:31:21 -05:00
|
|
|
import {WorldTime} from '../common/world-time';
|
2019-03-27 15:51:58 -05:00
|
|
|
import {createEntityForConnection} from './create-entity-for-connection';
|
|
|
|
import {createRoom} from './create-server-room';
|
2019-03-20 15:28:18 -05:00
|
|
|
// Create game.
|
2019-04-03 17:34:15 -05:00
|
|
|
export default function() {
|
|
|
|
setInterval(createMainLoop(), 1000 / 80);
|
|
|
|
return createConnectionListener();
|
2019-03-20 15:28:18 -05:00
|
|
|
}
|
2019-03-27 15:51:58 -05:00
|
|
|
// Create room.
|
|
|
|
const room = createRoom();
|
2019-04-04 07:31:21 -05:00
|
|
|
// Time :)
|
2019-04-04 17:18:55 -05:00
|
|
|
const worldTime = new WorldTime();
|
2019-04-07 14:14:05 -05:00
|
|
|
worldTime.hour = 10;
|
2019-03-27 01:52:55 -05:00
|
|
|
// Entity tracking.
|
|
|
|
const informables = [];
|
2019-04-07 20:04:34 -05:00
|
|
|
const synchronizer = new Synchronizer({
|
2019-03-27 01:52:55 -05:00
|
|
|
room,
|
2019-04-04 17:18:55 -05:00
|
|
|
worldTime,
|
2019-03-27 01:52:55 -05:00
|
|
|
});
|
2019-03-20 15:28:18 -05:00
|
|
|
// Connection listener.
|
2019-04-03 17:34:15 -05:00
|
|
|
function createConnectionListener() {
|
2019-03-20 15:28:18 -05:00
|
|
|
return (socket) => {
|
|
|
|
// Create and track a new entity for the connection.
|
2019-03-21 00:59:00 -05:00
|
|
|
const entity = createEntityForConnection(socket);
|
2019-03-27 15:51:58 -05:00
|
|
|
// Track informables.
|
|
|
|
informables.push(entity);
|
|
|
|
entity.on('destroyed', () => {
|
|
|
|
const index = informables.indexOf(entity);
|
|
|
|
if (-1 !== index) {
|
|
|
|
informables.splice(index, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// Add entity to room.
|
2019-03-27 17:16:09 -05:00
|
|
|
room.addEntityToLayer(entity, 'everything');
|
2019-04-08 08:01:17 -05:00
|
|
|
// Initial information.
|
|
|
|
entity.inform(synchronizer.state);
|
2019-03-20 15:28:18 -05:00
|
|
|
// Listen for events.
|
2019-04-03 17:34:15 -05:00
|
|
|
socket.on('message', createMessageListener(socket));
|
|
|
|
socket.on('disconnect', createDisconnectionListener(socket));
|
2019-03-20 15:28:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Handle incoming messages.
|
2019-04-03 17:34:15 -05:00
|
|
|
function createMessageListener(socket) {
|
2019-03-20 15:28:18 -05:00
|
|
|
const {entity} = socket;
|
|
|
|
return ({type, payload}) => {
|
|
|
|
switch (type) {
|
|
|
|
case 'input':
|
|
|
|
entity.inputState = payload;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
// Handle disconnection.
|
2019-04-03 17:34:15 -05:00
|
|
|
function createDisconnectionListener(socket) {
|
2019-03-20 15:28:18 -05:00
|
|
|
const {entity} = socket;
|
|
|
|
return () => {
|
2019-03-20 23:01:48 -05:00
|
|
|
entity.destroy();
|
2019-03-20 15:28:18 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
// Main loop.
|
|
|
|
let lastTime = performance.now();
|
2019-04-03 17:34:15 -05:00
|
|
|
function createMainLoop() {
|
2019-03-20 15:28:18 -05:00
|
|
|
return () => {
|
|
|
|
const now = performance.now();
|
|
|
|
const elapsed = (now - lastTime) / 1000;
|
|
|
|
lastTime = now;
|
2019-04-07 15:16:12 -05:00
|
|
|
// Tick synchronized.
|
2019-04-07 20:04:34 -05:00
|
|
|
synchronizer.tick(elapsed);
|
2019-04-07 14:59:55 -05:00
|
|
|
// Inform entities of the new state.
|
2019-03-21 00:59:00 -05:00
|
|
|
for (const entity of informables) {
|
2019-04-07 20:04:34 -05:00
|
|
|
entity.inform(synchronizer.state);
|
2019-03-20 18:35:59 -05:00
|
|
|
}
|
2019-03-20 15:28:18 -05:00
|
|
|
}
|
|
|
|
}
|