humus-old/server/game.js
2019-03-27 15:51:58 -05:00

79 lines
2.2 KiB
JavaScript

// Node.
import {performance} from 'perf_hooks';
// 3rd party.
import immutablediff from 'immutablediff';
// 2nd party.
import {StateSynchronizer} from '@avocado/state';
// 1st party.
import {createEntityForConnection} from './create-entity-for-connection';
import {createRoom} from './create-server-room';
// Create game.
export default function(avocadoServer) {
avocadoServer.on('connect', createConnectionListener(avocadoServer));
setInterval(createMainLoop(avocadoServer), 1000 / 80);
}
// Create room.
const room = createRoom();
// Entity tracking.
const informables = [];
const stateSynchronizer = new StateSynchronizer({
room,
});
// Connection listener.
function createConnectionListener(avocadoServer) {
return (socket) => {
// Create and track a new entity for the connection.
const entity = createEntityForConnection(socket);
// Track informables.
informables.push(entity);
entity.on('destroyed', () => {
const index = informables.indexOf(entity);
if (-1 !== index) {
informables.splice(index, 1);
}
});
// Add entity to room.
room.addEntityToLayer(entity, 0);
// Listen for events.
socket.on('message', createMessageListener(avocadoServer, socket));
socket.on('disconnect', createDisconnectionListener(avocadoServer, socket));
}
}
// Handle incoming messages.
function createMessageListener(avocadoServer, socket) {
const {entity} = socket;
return ({type, payload}) => {
switch (type) {
case 'input':
entity.inputState = payload;
break;
}
};
}
// Handle disconnection.
function createDisconnectionListener(avocadoServer, socket) {
const {entity} = socket;
return () => {
entity.destroy();
};
}
// Main loop.
let lastTime = performance.now();
function createMainLoop(avocadoServer) {
return () => {
const now = performance.now();
const elapsed = (now - lastTime) / 1000;
lastTime = now;
room.tick(elapsed);
const diff = stateSynchronizer.diff();
if (StateSynchronizer.noChange === diff) {
return;
}
// All informed entities get their own slice.
for (const entity of informables) {
const reduced = entity.reduceStateDiff(diff);
entity.inform(reduced);
}
}
}