-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
117 lines (89 loc) · 2.89 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
const ChampionList = require('./classes/ChampionList');
const GameList = require('./classes/GameList');
const Game = require('./classes/Game');
const createServer = require('./create-server');
const dayjs = require('dayjs');
const nanoid = import('nanoid');
const dictionary = require('nanoid-dictionary');
const generateId = (async () => (await nanoid).customAlphabet(dictionary.alphanumeric, 10))();
const onGameStateChange = game => {
io.to(`game.${game.getId()}`).emit('game-state', game.getState());
GameList.update(game.getId());
};
function validateGameCreation(input) {
if(!Array.isArray(input.teams) || input.teams.length !== 2 || typeof input.teams[0] !== 'string' || typeof input.teams[1] !== 'string') {
return false;
}
const cleanse = string => string.trim().substr(0, 30);
return {
teams: [
cleanse(input.teams[0]),
cleanse(input.teams[1]),
],
};
}
async function createGame(req, res) {
const input = validateGameCreation(req.body);
if(!input) {
res.end();
}
const game = new Game(await generateId, input.teams, ChampionList.get(), onGameStateChange);
const teams = game.getTeams();
GameList.add(game.getId(), game);
res.send({
game: game.getId(),
teams: teams.map(team => team.getId()),
});
}
function onJoinGame(socket) {
const game = GameList.get(socket.handshake.query.game);
if(game === undefined) {
socket.emit('game-expired');
socket.disconnect(true);
return;
}
socket.emit('champions', ChampionList.get());
socket.emit('server-time', Number(dayjs()));
socket.emit('assign-team', game.getTeamIndexById(socket.handshake.query.team));
socket.emit('game-state', game.getState());
socket.join(`game.${game.getId()}`);
}
function onGameAction(socket, data) {
const game = GameList.get(socket.handshake.query.game);
if(game === undefined) {
socket.emit('game-expired');
socket.disconnect(true);
return;
}
game.act(socket.handshake.query.team, data.action, data.value);
}
setInterval(async () => {
const expired = await GameList.flushExpired();
for(let id of expired) {
io.to(`game.${id}`).emit('game-expired');
}
}, 3600000); // 1 hour
// Ignoring errors is fine here, we'll just wait another hour to check for new champions
setInterval(() => ChampionList.update().catch(() => {}), 3600000); // 1 hour
async function startServer() {
const champions = await ChampionList.update();
await GameList.init(champions, onGameStateChange);
return createServer(createGame, onJoinGame, onGameAction);
}
let startServerInterval = null;
let io = null;
async function attemptStartServer() {
try {
io = await startServer();
if(startServerInterval !== null) {
clearInterval(startServerInterval);
startServerInterval = null;
}
} catch (e) {
console.error('Failed to load champion list and start the server.')
}
}
(async () => await attemptStartServer())();
if(io === null) {
startServerInterval = setInterval(attemptStartServer, 10000); // 10 seconds
}