-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.js
306 lines (265 loc) · 8.72 KB
/
server.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
const express = require('express');
const app = express();
const https = require('https');
const helmet = require('helmet');
const serve_static = require('serve-static');
const compression = require('compression');
app.use(helmet());
app.use(compression());
const socket = require('socket.io');
const fs = require('fs');
var rooms = {};
const json1 = JSON.parse(fs.readFileSync('./Storage/spyfall_1.json', 'utf8'));
const json2 = JSON.parse(fs.readFileSync('./Storage/spyfall_2.json', 'utf8'));
const json3 = JSON.parse(fs.readFileSync('./Storage/custom_1.json', 'utf-8'));
const users_json = JSON.parse(fs.readFileSync('./Storage/users.json', 'utf-8'));
const https_key_config = https.createServer(
{
key: fs.readFileSync('/etc/letsencrypt/live/spyfall.groups.id/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/spyfall.groups.id/fullchain.pem')
},
app
);
const server = https_key_config.listen(443, () => {
console.log('spyfall.groups.id is listening on port 443!');
});
// feeding our app the folder containing all of our frontend pages
app.use(
serve_static('frontend', {
extensions: ['html'],
dotfiles: 'deny', // strictly deny all access to any directory containing a "." in case we want to hide files
index: ['index.html']
})
);
const io = socket(server, { cookie: false });
io.on('connection', socket => {
console.log(
'New ' +
(socket.handshake.secure ? 'secure' : 'insecure') +
' connection from socket ' +
socket.id +
' on' +
socket.handshake['headers']['user-agent'].split(';')[1] +
' in the ' +
socket.handshake['headers']['referer']
.split('/')[3]
.split('?')[0]
.split('_')
.join(' ') +
' page.'
);
if (socket.handshake['headers']['referer'].split('/')[3].split('?')[0] == 'game_room') {
logUser(socket.handshake['headers']['user-agent'].split(';')[1].trim());
}
// When a user clicks the 'create' button on the website, this will run
socket.on('create', data => {
let key_to_send = keyCreator();
// set up the preferences of the room based on the create room screen choices
rooms[key_to_send]['prefs'] = {};
rooms[key_to_send]['players'] = {};
rooms[key_to_send]['prefs'].spy1on = data.spyfall1on;
rooms[key_to_send]['prefs'].spy2on = data.spyfall2on;
rooms[key_to_send]['prefs'].cus1on = data.custom1on;
rooms[key_to_send]['prefs'].matchtime = data.time;
rooms[key_to_send]['prefs'].owner = data.name;
rooms[key_to_send]['prefs'].gamestate = 'down';
// emit the created key back to the frontend
io.to(data.source_socket).emit('create', {
back_data: data,
key: key_to_send
});
});
// When a user clicks the 'join' button on the website, this will run
socket.on('join', data => {
// if the room doesn't exist...
if (!rooms[data.join_key]) {
return io.to(data.source_socket).emit('no_key_error', data.join_key);
} else {
io.to(data.source_socket).emit('join', {
back_data: data,
key: data.join_key
});
}
});
// when a player enters the game_room, this will run
socket.on('load_players', data => {
// If the room they are trying to load doesnt exist
if (!rooms[data.key]) {
io.to(data.source_socket).emit('no_key_error', data.key);
return;
}
// put the players socket and name into the room
rooms[data.key]['players'][data.source_socket] = data.name;
// reload the players with the updated information
for (let e of Object.keys(rooms[data.key]['players'])) {
io.to(e).emit('load_players', {
player_sockets: Object.keys(rooms[data.key]['players']),
player_names: Object.values(rooms[data.key]['players']),
gamestate: rooms[data.key]['prefs'].gamestate
});
}
});
// when a user clicks "start game" this will get run
socket.on('start_game', data => {
// array to store the locations and roles that are in play
let temp_locations = getLocations(rooms[data.key]['prefs'].spy1on, rooms[data.key]['prefs'].spy2on, rooms[data.key]['prefs'].cus1on);
let chosen_location = temp_locations[Math.floor(Math.random() * temp_locations.length)];
let temp_roles = getRoles(chosen_location);
rooms[data.key]['prefs'].gamestate = 'up';
// choose a spy from the numer of sockets connected to the room
let spy_num = Math.floor(Math.random() * Object.keys(rooms[data.key]['players']).length);
for (i = 0; i < Object.keys(rooms[data.key]['players']).length; i++) {
if (i == spy_num) {
// if the current for loop is on the person chosen to be the spy
io.to(Object.keys(rooms[data.key]['players'])[i]).emit('start_game', {
location: chosen_location,
role: 'spy',
time: rooms[data.key]['prefs'].matchtime,
locations: temp_locations
});
} else {
// else, choose a random role from the chosen location
io.to(Object.keys(rooms[data.key]['players'])[i]).emit('start_game', {
location: chosen_location,
role: temp_roles[Math.floor(Math.random() * temp_roles.length)],
time: rooms[data.key]['prefs'].matchtime,
locations: temp_locations
});
}
}
});
socket.on('game_stop', data => {
rooms[data]['prefs'].gamestate = 'down';
for (let i of Object.keys(rooms[data]['players'])) {
io.to(i).emit('game_stop', data);
}
});
// ran whenever a socket disconnects
socket.on('disconnect', () => {
for (let key in rooms) {
// if that player is connected to a valid room....
if (rooms[key]['players'][socket.id]) {
// then delete them from that room....
delete rooms[key]['players'][socket.id];
// and update the list of players for everyone else in the room.
for (let i of Object.keys(rooms[key]['players'])) {
io.to(i).emit('load_players', {
player_sockets: Object.keys(rooms[key]['players']),
player_names: Object.values(rooms[key]['players'])
});
}
}
}
for (let key in rooms) {
if (objectIsEmpty(rooms[key]['players'])) {
}
}
});
});
// Function to create a unique five letter key.
function keyCreator() {
let alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let temp_key =
alphabet[Math.floor(Math.random() * 25)] +
alphabet[Math.floor(Math.random() * 25)] +
alphabet[Math.floor(Math.random() * 25)] +
alphabet[Math.floor(Math.random() * 25)] +
alphabet[Math.floor(Math.random() * 25)];
if (rooms[temp_key]) {
// if the key already exists, we got some nice recursion
keyCreator();
} else {
// otherwise, create this area in the rooms object
rooms[temp_key] = {};
return temp_key;
}
}
function objectIsEmpty(obj) {
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) return false;
}
return true;
}
function getLocations(spy1, spy2, cus1) {
let temp_array = [];
if (spy1) {
temp_array.push(Object.keys(json1));
}
if (spy2) {
temp_array.push(Object.keys(json2));
}
if (cus1) {
temp_array.push(Object.keys(json3));
}
return [].concat.apply([], temp_array);
}
function getRoles(location) {
let temp_array = [];
for (let key in json1) {
if (key == location) {
temp_array.push(json1[key].role1);
temp_array.push(json1[key].role2);
temp_array.push(json1[key].role3);
temp_array.push(json1[key].role4);
temp_array.push(json1[key].role5);
temp_array.push(json1[key].role6);
temp_array.push(json1[key].role7);
}
}
for (let key in json2) {
if (key == location) {
temp_array.push(json2[key].role1);
temp_array.push(json2[key].role2);
temp_array.push(json2[key].role3);
temp_array.push(json2[key].role4);
temp_array.push(json2[key].role5);
temp_array.push(json2[key].role6);
temp_array.push(json2[key].role7);
temp_array.push(json2[key].role8);
temp_array.push(json2[key].role9);
}
}
for (let key in json3) {
if (key == location) {
temp_array.push(json3[key].role1);
temp_array.push(json3[key].role2);
temp_array.push(json3[key].role3);
temp_array.push(json3[key].role4);
temp_array.push(json3[key].role5);
temp_array.push(json3[key].role6);
temp_array.push(json3[key].role7);
}
}
return [].concat.apply([], temp_array);
}
let uptime = 0;
let last_sec = 0;
// Get second precision down to a tenth of a second
setInterval(() => {
var today = new Date();
let second = today.getSeconds();
if (last_sec != second) {
last_sec = second;
++uptime;
for (let key in rooms) {
for (let e of Object.keys(rooms[key]['players'])) {
io.to(e).emit('event_tick', {
uptime: uptime,
to_socket: e,
room_up: rooms[key]['prefs'].gamestate
});
}
}
}
}, 100);
async function logUser(user_system) {
if (!users_json) users_json = {};
if (!users_json[user_system]) {
users_json[user_system] = { connections: 1 };
} else {
users_json[user_system].connections = users_json[user_system].connections + 1;
}
fs.writeFile('Storage/users.json', JSON.stringify(users_json, null, 4), err => {
if (err) console.error(err);
});
}