snakeia-server 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.drone.yml +2 -1
- package/GameEngineMultithreading.js +97 -44
- package/GameEngineMultithreadingController.js +136 -105
- package/Player.js +132 -0
- package/README.md +34 -4
- package/assets/css/dark-theme.css +103 -0
- package/config/default.json +4 -1
- package/package.json +6 -6
- package/server.js +159 -193
- package/views/admin.html +7 -0
- package/views/authentication.html +7 -0
- package/views/banned.html +7 -0
- package/views/index.html +7 -0
package/server.js
CHANGED
|
@@ -40,12 +40,8 @@ const { doubleCsrf } = require("csrf-csrf");
|
|
|
40
40
|
const bodyParser = require("body-parser");
|
|
41
41
|
const node_config = require("config");
|
|
42
42
|
|
|
43
|
-
const games = {}; // Contains all the games processed by the server
|
|
44
43
|
process.env["ALLOW_CONFIG_MUTATIONS"] = true;
|
|
45
44
|
let config = node_config.get("ServerConfig"); // Server configuration (see default config file config.json)
|
|
46
|
-
const tokens = []; // User tokens
|
|
47
|
-
const invalidatedUserTokens = []; // Invalidated user tokens
|
|
48
|
-
const invalidatedAdminTokens = []; // Invalidated admin tokens
|
|
49
45
|
|
|
50
46
|
// Load config file
|
|
51
47
|
const configSources = node_config.util.getConfigSources();
|
|
@@ -101,110 +97,12 @@ const Snake = snakeia.Snake;
|
|
|
101
97
|
const Grid = snakeia.Grid;
|
|
102
98
|
const GameConstants = snakeia.GameConstants;
|
|
103
99
|
const GameEngine = config.enableMultithreading ? require("./GameEngineMultithreadingController")(logger) : snakeia.GameEngine;
|
|
100
|
+
const Player = require("./Player");
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.snake = snake;
|
|
110
|
-
this.ready = ready;
|
|
111
|
-
this.version = version;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
get username() {
|
|
115
|
-
return Player.getUsername(this);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
static getPlayer(array, id) {
|
|
119
|
-
for(let i = 0; i < array.length; i++) {
|
|
120
|
-
if(array[i] != null && array[i].id == id) {
|
|
121
|
-
return array[i];
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
static getPlayerAllGames(id) {
|
|
129
|
-
const keys = Object.keys(games);
|
|
130
|
-
|
|
131
|
-
for(let i = 0; i < keys.length; i++) {
|
|
132
|
-
const game = games[keys[i]];
|
|
133
|
-
|
|
134
|
-
if(game) {
|
|
135
|
-
const p = this.getPlayer(game.players, id);
|
|
136
|
-
const p2 = this.getPlayer(game.spectators, id);
|
|
137
|
-
if(p) return p;
|
|
138
|
-
if(p2) return p2;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
static getPlayerToken(array, token) {
|
|
146
|
-
if(!token) return null;
|
|
147
|
-
for(let i = 0; i < array.length; i++) {
|
|
148
|
-
if(array[i] != null && array[i].token == token) {
|
|
149
|
-
return array[i];
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
static getPlayerAllGamesToken(token) {
|
|
157
|
-
if(!token) return null;
|
|
158
|
-
const keys = Object.keys(games);
|
|
159
|
-
|
|
160
|
-
for(let i = 0; i < keys.length; i++) {
|
|
161
|
-
const game = games[keys[i]];
|
|
162
|
-
|
|
163
|
-
if(game) {
|
|
164
|
-
const p = this.getPlayerToken(game.players, token);
|
|
165
|
-
const p2 = this.getPlayerToken(game.spectators, token);
|
|
166
|
-
if(p) return p;
|
|
167
|
-
if(p2) return p2;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
static containsId(array, id) {
|
|
175
|
-
return Player.getPlayer(array, id) != null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static containsToken(array, token) {
|
|
179
|
-
return Player.getPlayerToken(array, token) != null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
static containsIdAllGames(id) {
|
|
183
|
-
return Player.getPlayerAllGames(id) != null;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
static containsTokenAllGames(token) {
|
|
187
|
-
return Player.getPlayerAllGamesToken(token) != null;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
static getUsername(player) {
|
|
191
|
-
try {
|
|
192
|
-
const decoded_token = jwt.verify(player.token, jsonWebTokenSecretKey);
|
|
193
|
-
return decoded_token && decoded_token.username ? decoded_token.username : null;
|
|
194
|
-
} catch(e) {
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
static getUsernameSocket(socket) {
|
|
200
|
-
try {
|
|
201
|
-
const decoded_token = jwt.verify(socket.handshake.auth.token || socket.handshake.query.token || socket.request.cookies.token, jsonWebTokenSecretKey);
|
|
202
|
-
return decoded_token && decoded_token.username ? decoded_token.username : null;
|
|
203
|
-
} catch(e) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
102
|
+
const games = {}; // Contains all the games processed by the server
|
|
103
|
+
const tokens = []; // User tokens
|
|
104
|
+
const invalidatedUserTokens = []; // Invalidated user tokens
|
|
105
|
+
const invalidatedAdminTokens = []; // Invalidated admin tokens
|
|
208
106
|
|
|
209
107
|
function getRoomsData() {
|
|
210
108
|
const rooms = [];
|
|
@@ -219,20 +117,20 @@ function getRoomsData() {
|
|
|
219
117
|
rooms[i]["players"] = Object.keys(game["players"]).length + game.numberAIToAdd;
|
|
220
118
|
rooms[i]["width"] = "???";
|
|
221
119
|
rooms[i]["height"] = "???";
|
|
222
|
-
rooms[i]["speed"] = game["
|
|
120
|
+
rooms[i]["speed"] = game["gameEngine"].speed;
|
|
223
121
|
rooms[i]["code"] = keysRooms[i];
|
|
224
122
|
rooms[i]["maxPlayers"] = getMaxPlayers(keysRooms[i]);
|
|
225
123
|
rooms[i]["state"] = (game["started"] ? GameConstants.GameState.STARTED : game["timeoutPlay"] != null ? GameConstants.GameState.STARTING : game["searchingPlayers"] ? GameConstants.GameState.SEARCHING_PLAYERS : "");
|
|
226
124
|
|
|
227
|
-
if(game["
|
|
228
|
-
rooms[i]["width"] = game["
|
|
229
|
-
rooms[i]["height"] = game["
|
|
230
|
-
rooms[i]["borderWalls"] = game["
|
|
231
|
-
rooms[i]["generateWalls"] = game["
|
|
125
|
+
if(game["gameEngine"].grid != null) {
|
|
126
|
+
rooms[i]["width"] = game["gameEngine"].grid.width;
|
|
127
|
+
rooms[i]["height"] = game["gameEngine"].grid.height;
|
|
128
|
+
rooms[i]["borderWalls"] = game["gameEngine"].grid.borderWalls;
|
|
129
|
+
rooms[i]["generateWalls"] = game["gameEngine"].grid.generateWalls;
|
|
232
130
|
}
|
|
233
131
|
|
|
234
|
-
if(game["
|
|
235
|
-
rooms[i]["players"] = game["
|
|
132
|
+
if(game["gameEngine"].snake != null) {
|
|
133
|
+
rooms[i]["players"] = game["gameEngine"].snake.length;
|
|
236
134
|
}
|
|
237
135
|
|
|
238
136
|
if(game["spectators"] != null) {
|
|
@@ -264,7 +162,7 @@ function generateRandomJsonWebTokenSecretKey(precValue) {
|
|
|
264
162
|
}
|
|
265
163
|
|
|
266
164
|
function getMaxPlayers(code) {
|
|
267
|
-
const game = games[code].
|
|
165
|
+
const game = games[code].gameEngine;
|
|
268
166
|
|
|
269
167
|
const heightGrid = parseInt(game.grid.height);
|
|
270
168
|
const widthGrid = parseInt(game.grid.width);
|
|
@@ -287,7 +185,7 @@ function getMaxPlayers(code) {
|
|
|
287
185
|
}
|
|
288
186
|
|
|
289
187
|
function createRoom(data, socket) {
|
|
290
|
-
if(Object.keys(games).filter(key => games[key] != null).length < config.maxRooms && !Player.containsTokenAllGames(socket
|
|
188
|
+
if(Object.keys(games).filter(key => games[key] != null).length < config.maxRooms && !Player.containsTokenAllGames(socket?.handshake?.auth?.token || socket?.handshake?.query?.token || socket?.request?.cookies?.token, games) && !Player.containsIdAllGames(socket.id, games)) {
|
|
291
189
|
let heightGrid = 20;
|
|
292
190
|
let widthGrid = 20;
|
|
293
191
|
let borderWalls = false;
|
|
@@ -357,10 +255,14 @@ function createRoom(data, socket) {
|
|
|
357
255
|
const grid = new Grid(widthGrid, heightGrid, generateWalls, borderWalls, false, null, false);
|
|
358
256
|
grid.reset();
|
|
359
257
|
grid.init();
|
|
360
|
-
const game = new GameEngine(grid, [], speed
|
|
258
|
+
const game = new GameEngine(grid, [], speed, null, null, null, null, null, {
|
|
259
|
+
modelListAPIURL: config.aiUltraAPIURL,
|
|
260
|
+
modelID: config.aiUltraCustomModelURL ? "custom" : config.aiUltraModelID,
|
|
261
|
+
customURL: config.aiUltraCustomModelURL
|
|
262
|
+
});
|
|
361
263
|
|
|
362
264
|
games[code] = {
|
|
363
|
-
|
|
265
|
+
gameEngine: game,
|
|
364
266
|
private: privateGame,
|
|
365
267
|
players: [],
|
|
366
268
|
spectators: [],
|
|
@@ -402,7 +304,7 @@ function createRoom(data, socket) {
|
|
|
402
304
|
});
|
|
403
305
|
}
|
|
404
306
|
} else if(socket != null) {
|
|
405
|
-
if(Player.containsTokenAllGames(socket
|
|
307
|
+
if(Player.containsTokenAllGames(socket?.handshake?.auth?.token || socket?.handshake?.query?.token || socket?.request?.cookies?.token, games) || Player.containsIdAllGames(socket.id, games)) {
|
|
406
308
|
socket.emit("process", {
|
|
407
309
|
success: false,
|
|
408
310
|
code: null,
|
|
@@ -419,20 +321,57 @@ function createRoom(data, socket) {
|
|
|
419
321
|
}
|
|
420
322
|
|
|
421
323
|
function copySnakes(snakes) {
|
|
422
|
-
const
|
|
324
|
+
const snakesCopy = [];
|
|
423
325
|
|
|
424
|
-
if(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
326
|
+
if(snakes) {
|
|
327
|
+
snakes.forEach(snake => {
|
|
328
|
+
if(snake) {
|
|
329
|
+
const snakeCopy = new Snake();
|
|
330
|
+
|
|
331
|
+
snakeCopy.color = snake.color;
|
|
332
|
+
snakeCopy.direction = snake.direction;
|
|
333
|
+
snakeCopy.errorInit = snake.errorInit;
|
|
334
|
+
snakeCopy.gameOver = snake.gameOver;
|
|
335
|
+
snakeCopy.autoRetry = snake.autoRetry;
|
|
336
|
+
snakeCopy.aiLevel = snake.aiLevel;
|
|
337
|
+
|
|
338
|
+
if(snake.lastTail) {
|
|
339
|
+
snakeCopy.lastTail = JSON.parse(JSON.stringify(snake.lastTail));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if(snake.lastHead) {
|
|
343
|
+
snakeCopy.lastHead = JSON.parse(JSON.stringify(snake.lastHead));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
snakeCopy.lastTailMoved = snake.lastTailMoved;
|
|
347
|
+
snakeCopy.lastHeadMoved = snake.lastHeadMoved;
|
|
348
|
+
snakeCopy.name = snake.name;
|
|
349
|
+
snakeCopy.player = snake.player;
|
|
350
|
+
|
|
351
|
+
if(snake.queue) {
|
|
352
|
+
snakeCopy.queue = JSON.parse(JSON.stringify(snake.queue));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
snakeCopy.score = snake.score;
|
|
356
|
+
snakeCopy.scoreMax = snake.scoreMax;
|
|
357
|
+
snakeCopy.ticksDead = snake.ticksDead;
|
|
358
|
+
snakeCopy.ticksWithoutAction = snake.ticksWithoutAction;
|
|
359
|
+
snakeCopy.grid = null;
|
|
360
|
+
|
|
361
|
+
if(snake.snakeAI && snake.snakeAI.aiLevelText) {
|
|
362
|
+
snakeCopy.snakeAI.aiLevelText = snake.snakeAI.aiLevelText;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
snakesCopy.push(snakeCopy);
|
|
366
|
+
}
|
|
428
367
|
});
|
|
429
368
|
}
|
|
430
369
|
|
|
431
|
-
return
|
|
370
|
+
return snakesCopy;
|
|
432
371
|
}
|
|
433
372
|
|
|
434
373
|
function setupRoom(code) {
|
|
435
|
-
const game = games[code].
|
|
374
|
+
const game = games[code].gameEngine;
|
|
436
375
|
|
|
437
376
|
game.onReset(() => {
|
|
438
377
|
io.to("room-" + code).emit("reset", {
|
|
@@ -622,8 +561,8 @@ function cleanRooms() {
|
|
|
622
561
|
if(nb <= 0) {
|
|
623
562
|
toRemove.push(keys[i]);
|
|
624
563
|
|
|
625
|
-
if(game.
|
|
626
|
-
game.
|
|
564
|
+
if(game.gameEngine && game.gameEngine.kill) {
|
|
565
|
+
game.gameEngine.kill();
|
|
627
566
|
}
|
|
628
567
|
}
|
|
629
568
|
}
|
|
@@ -672,13 +611,14 @@ function gameMatchmaking(game, code) {
|
|
|
672
611
|
"playerNumber": numberPlayers,
|
|
673
612
|
"maxPlayers": getMaxPlayers(code),
|
|
674
613
|
"spectatorMode": false,
|
|
675
|
-
"errorOccurred": game.
|
|
614
|
+
"errorOccurred": game.gameEngine.errorOccurred,
|
|
676
615
|
"onlineMaster": false,
|
|
677
616
|
"onlineMode": true,
|
|
678
617
|
"enableRetryPauseMenu": false,
|
|
679
618
|
"countBeforePlay": game.countBeforePlay,
|
|
680
|
-
"initialSpeed": game.
|
|
681
|
-
"speed": game.
|
|
619
|
+
"initialSpeed": game.gameEngine.initialSpeed,
|
|
620
|
+
"speed": game.gameEngine.speed,
|
|
621
|
+
"errorOccured": game.gameEngine.errorOccured
|
|
682
622
|
});
|
|
683
623
|
|
|
684
624
|
io.to(game.players[0].id).emit("init", {
|
|
@@ -690,7 +630,7 @@ function gameMatchmaking(game, code) {
|
|
|
690
630
|
setupSpectators(code);
|
|
691
631
|
}
|
|
692
632
|
|
|
693
|
-
function startGame(code) {
|
|
633
|
+
async function startGame(code) {
|
|
694
634
|
const game = games[code];
|
|
695
635
|
|
|
696
636
|
if(game != null) {
|
|
@@ -701,15 +641,15 @@ function startGame(code) {
|
|
|
701
641
|
|
|
702
642
|
game.searchingPlayers = false;
|
|
703
643
|
game.started = true;
|
|
704
|
-
game.
|
|
705
|
-
game.
|
|
706
|
-
game.
|
|
644
|
+
game.gameEngine.snakes = [];
|
|
645
|
+
game.gameEngine.grid.reset();
|
|
646
|
+
game.gameEngine.grid.init();
|
|
707
647
|
|
|
708
648
|
for(let i = 0; i < game.players.length; i++) {
|
|
709
649
|
const username = game.players[i].username;
|
|
710
650
|
|
|
711
|
-
game.players[i].snake = new Snake(null, null, game.
|
|
712
|
-
game.
|
|
651
|
+
game.players[i].snake = new Snake(null, null, game.gameEngine.grid, null, null, null, username);
|
|
652
|
+
game.gameEngine.snakes.push(game.players[i].snake);
|
|
713
653
|
|
|
714
654
|
io.to(game.players[i].id).emit("init", {
|
|
715
655
|
"currentPlayer": (i + 1),
|
|
@@ -719,29 +659,38 @@ function startGame(code) {
|
|
|
719
659
|
|
|
720
660
|
if(game.enableAI) {
|
|
721
661
|
for(let i = 0; i < game.numberAIToAdd; i++) {
|
|
722
|
-
const snakeAI = new Snake(null, null, game.
|
|
723
|
-
game.
|
|
662
|
+
const snakeAI = new Snake(null, null, game.gameEngine.grid, GameConstants.PlayerType.AI, game.levelAI);
|
|
663
|
+
game.gameEngine.snakes.push(snakeAI);
|
|
724
664
|
}
|
|
725
665
|
}
|
|
726
666
|
|
|
727
667
|
if(config.enableMaxTimeGame) {
|
|
728
668
|
clearTimeout(game.timeoutMaxTimePlay);
|
|
729
|
-
game.
|
|
669
|
+
game.gameEngine.timeStart = Date.now() + 5000;
|
|
730
670
|
game.timeoutMaxTimePlay = setTimeout(() => {
|
|
731
|
-
game.
|
|
671
|
+
game.gameEngine.stop(true);
|
|
732
672
|
}, config.maxTimeGame + 5000);
|
|
733
673
|
}
|
|
674
|
+
|
|
675
|
+
io.to("room-" + code).emit("init", {
|
|
676
|
+
"engineLoading": true
|
|
677
|
+
});
|
|
734
678
|
|
|
735
679
|
if(!game.alreadyInit) {
|
|
736
|
-
game.
|
|
737
|
-
game.
|
|
680
|
+
await game.gameEngine.init();
|
|
681
|
+
game.gameEngine.start();
|
|
738
682
|
game.alreadyInit = true;
|
|
739
683
|
} else {
|
|
740
|
-
game.
|
|
741
|
-
game.
|
|
742
|
-
game.
|
|
684
|
+
game.gameEngine.countBeforePlay = 3;
|
|
685
|
+
await game.gameEngine.init();
|
|
686
|
+
game.gameEngine.reset();
|
|
743
687
|
}
|
|
744
688
|
|
|
689
|
+
io.to("room-" + code).emit("init", {
|
|
690
|
+
"errorOccurred": game.gameEngine.errorOccurred,
|
|
691
|
+
"engineLoading": false
|
|
692
|
+
});
|
|
693
|
+
|
|
745
694
|
setupSpectators(code);
|
|
746
695
|
}
|
|
747
696
|
}
|
|
@@ -754,7 +703,8 @@ function setupSpectators(code) {
|
|
|
754
703
|
io.to(game.spectators[i].id).emit("init", {
|
|
755
704
|
"spectatorMode": true,
|
|
756
705
|
"onlineMode": true,
|
|
757
|
-
"enableRetryPauseMenu": false
|
|
706
|
+
"enableRetryPauseMenu": false,
|
|
707
|
+
"engineLoading": false
|
|
758
708
|
});
|
|
759
709
|
}
|
|
760
710
|
}
|
|
@@ -766,8 +716,8 @@ function sendStatus(code) {
|
|
|
766
716
|
|
|
767
717
|
if(game != null) {
|
|
768
718
|
for(let i = 0; i < game.players.length; i++) {
|
|
769
|
-
game.
|
|
770
|
-
if(game.players[i].snake.gameOver) game.
|
|
719
|
+
game.gameEngine.key(game.players[i].snake.lastKey, i + 1);
|
|
720
|
+
if(game.players[i].snake.gameOver) game.gameEngine.setGameOver(i + 1);
|
|
771
721
|
}
|
|
772
722
|
}
|
|
773
723
|
}
|
|
@@ -917,7 +867,8 @@ app.use("/authentication", rateLimit({
|
|
|
917
867
|
app.use(function(req, res, next) {
|
|
918
868
|
ipBanned(req.ip).then(() => {
|
|
919
869
|
res.render(__dirname + "/views/banned.html", {
|
|
920
|
-
contact: config.contactBan
|
|
870
|
+
contact: config.contactBan,
|
|
871
|
+
theme: req.query.theme
|
|
921
872
|
});
|
|
922
873
|
res.end();
|
|
923
874
|
}, () => {
|
|
@@ -928,7 +879,8 @@ app.use(function(req, res, next) {
|
|
|
928
879
|
app.get("/", function(req, res) {
|
|
929
880
|
res.render(__dirname + "/views/index.html", {
|
|
930
881
|
version: config.version,
|
|
931
|
-
engineVersion: GameConstants.Setting.APP_VERSION
|
|
882
|
+
engineVersion: GameConstants.Setting.APP_VERSION,
|
|
883
|
+
theme: req.query.theme
|
|
932
884
|
});
|
|
933
885
|
});
|
|
934
886
|
|
|
@@ -950,7 +902,8 @@ app.get("/authentication", function(req, res) {
|
|
|
950
902
|
min: config.minCharactersUsername,
|
|
951
903
|
max: config.maxCharactersUsername,
|
|
952
904
|
enableMaxTimeGame: config.enableMaxTimeGame,
|
|
953
|
-
maxTimeGame: config.maxTimeGame
|
|
905
|
+
maxTimeGame: config.maxTimeGame,
|
|
906
|
+
theme: req.query.theme
|
|
954
907
|
});
|
|
955
908
|
});
|
|
956
909
|
} else {
|
|
@@ -987,7 +940,8 @@ app.post("/authentication", function(req, res) {
|
|
|
987
940
|
min: config.minCharactersUsername,
|
|
988
941
|
max: config.maxCharactersUsername,
|
|
989
942
|
enableMaxTimeGame: config.enableMaxTimeGame,
|
|
990
|
-
maxTimeGame: config.maxTimeGame
|
|
943
|
+
maxTimeGame: config.maxTimeGame,
|
|
944
|
+
theme: req.query.theme
|
|
991
945
|
});
|
|
992
946
|
|
|
993
947
|
logger.info("authentication - username: " + username + " - ip: " + req.ip);
|
|
@@ -1009,7 +963,8 @@ app.post("/authentication", function(req, res) {
|
|
|
1009
963
|
min: config.minCharactersUsername,
|
|
1010
964
|
max: config.maxCharactersUsername,
|
|
1011
965
|
enableMaxTimeGame: config.enableMaxTimeGame,
|
|
1012
|
-
maxTimeGame: config.maxTimeGame
|
|
966
|
+
maxTimeGame: config.maxTimeGame,
|
|
967
|
+
theme: req.query.theme
|
|
1013
968
|
});
|
|
1014
969
|
});
|
|
1015
970
|
}
|
|
@@ -1032,9 +987,11 @@ app.get("/rooms", function(req, res) {
|
|
|
1032
987
|
|
|
1033
988
|
// Admin panel
|
|
1034
989
|
function kickUser(socketId, token) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
990
|
+
const sockets = io.of("/").sockets;
|
|
991
|
+
|
|
992
|
+
if(sockets.get(socketId)) {
|
|
993
|
+
logger.info("user kicked (socket: " + socketId + ") - ip: " + getIPSocketIO(sockets.get(socketId).handshake));
|
|
994
|
+
sockets.get(socketId).disconnect(true);
|
|
1038
995
|
invalidateUserToken(token);
|
|
1039
996
|
}
|
|
1040
997
|
}
|
|
@@ -1060,8 +1017,10 @@ function invalidateUserToken(token) {
|
|
|
1060
1017
|
}
|
|
1061
1018
|
|
|
1062
1019
|
function banUserIP(socketId) {
|
|
1063
|
-
|
|
1064
|
-
|
|
1020
|
+
const sockets = io.of("/").sockets;
|
|
1021
|
+
|
|
1022
|
+
if(sockets.get(socketId)) {
|
|
1023
|
+
let ip = getIPSocketIO(sockets.get(socketId).handshake);
|
|
1065
1024
|
|
|
1066
1025
|
if(ip && ip.substr(0, 7) == "::ffff:") {
|
|
1067
1026
|
ip = ip.substr(7, ip.length);
|
|
@@ -1219,7 +1178,8 @@ app.get("/admin", doubleCsrfProtection, function(req, res) {
|
|
|
1219
1178
|
csrfToken: generateCsrfToken(req, res, { overwrite: true, validateOnReuse: true }),
|
|
1220
1179
|
serverLog: logFile,
|
|
1221
1180
|
errorLog: errorLogFile,
|
|
1222
|
-
getIPSocketIO: getIPSocketIO
|
|
1181
|
+
getIPSocketIO: getIPSocketIO,
|
|
1182
|
+
theme: req.query.theme
|
|
1223
1183
|
});
|
|
1224
1184
|
});
|
|
1225
1185
|
});
|
|
@@ -1356,7 +1316,8 @@ app.post("/admin", adminRateLimiter, function(req, res) {
|
|
|
1356
1316
|
csrfToken: null,
|
|
1357
1317
|
serverLog: null,
|
|
1358
1318
|
errorLog: null,
|
|
1359
|
-
getIPSocketIO: getIPSocketIO
|
|
1319
|
+
getIPSocketIO: getIPSocketIO,
|
|
1320
|
+
theme: req.query.theme
|
|
1360
1321
|
});
|
|
1361
1322
|
});
|
|
1362
1323
|
}
|
|
@@ -1406,22 +1367,24 @@ function checkAuthentication(token) {
|
|
|
1406
1367
|
}
|
|
1407
1368
|
|
|
1408
1369
|
function checkAuthenticationSocket(socket) {
|
|
1409
|
-
return checkAuthentication(socket
|
|
1370
|
+
return checkAuthentication(socket?.handshake?.auth?.token || socket?.handshake?.query?.token || socket?.request?.cookies?.token);
|
|
1410
1371
|
}
|
|
1411
1372
|
|
|
1412
1373
|
function checkAuthenticationExpress(req) {
|
|
1413
1374
|
return checkAuthentication(req.cookies.token);
|
|
1414
1375
|
}
|
|
1415
1376
|
|
|
1416
|
-
|
|
1377
|
+
const checkBanned = function(socket, next) {
|
|
1417
1378
|
ipBanned(getIPSocketIO(socket.handshake)).then(() => {
|
|
1418
1379
|
next(new Error(GameConstants.Error.BANNED));
|
|
1419
1380
|
}, () => {
|
|
1420
1381
|
next();
|
|
1421
1382
|
});
|
|
1422
|
-
}
|
|
1383
|
+
};
|
|
1384
|
+
|
|
1385
|
+
io.use(checkBanned);
|
|
1423
1386
|
|
|
1424
|
-
io.of("/rooms").on("connection", function(socket) {
|
|
1387
|
+
io.of("/rooms").use(ioCookieParser()).use(checkBanned).on("connection", function(socket) {
|
|
1425
1388
|
checkAuthenticationSocket(socket).then(() => {
|
|
1426
1389
|
socket.emit("rooms", {
|
|
1427
1390
|
rooms: getRoomsData(),
|
|
@@ -1441,7 +1404,7 @@ io.of("/rooms").on("connection", function(socket) {
|
|
|
1441
1404
|
});
|
|
1442
1405
|
});
|
|
1443
1406
|
|
|
1444
|
-
io.of("/createRoom").on("connection", function(socket) {
|
|
1407
|
+
io.of("/createRoom").use(ioCookieParser()).use(checkBanned).on("connection", function(socket) {
|
|
1445
1408
|
socket.on("create", function(data) {
|
|
1446
1409
|
checkAuthenticationSocket(socket).then(() => {
|
|
1447
1410
|
createRoom(data, socket);
|
|
@@ -1461,7 +1424,7 @@ io.on("connection", function(socket) {
|
|
|
1461
1424
|
const version = data.version;
|
|
1462
1425
|
const game = games[code];
|
|
1463
1426
|
|
|
1464
|
-
if(game != null && !Player.containsId(game.players, socket.id) && !Player.containsId(game.spectators, socket.id) && !Player.containsToken(game.players, token) && !Player.containsToken(game.spectators, token) && !Player.containsTokenAllGames(token) && !Player.containsIdAllGames(socket.id)) {
|
|
1427
|
+
if(game != null && !Player.containsId(game.players, socket.id) && !Player.containsId(game.spectators, socket.id) && !Player.containsToken(game.players, token) && !Player.containsToken(game.spectators, token) && !Player.containsTokenAllGames(token, games) && !Player.containsIdAllGames(socket.id, games)) {
|
|
1465
1428
|
socket.join("room-" + code);
|
|
1466
1429
|
|
|
1467
1430
|
if(game.players.length + game.numberAIToAdd >= getMaxPlayers(code) || game.started) {
|
|
@@ -1481,37 +1444,40 @@ io.on("connection", function(socket) {
|
|
|
1481
1444
|
|
|
1482
1445
|
if(game.started) {
|
|
1483
1446
|
socket.emit("init", {
|
|
1484
|
-
"paused": game.
|
|
1485
|
-
"isReseted": game.
|
|
1486
|
-
"exited": game.
|
|
1487
|
-
"snakes": copySnakes(game.
|
|
1488
|
-
"grid": game.
|
|
1489
|
-
"numFruit": game.
|
|
1490
|
-
"ticks": game.
|
|
1491
|
-
"scoreMax": game.
|
|
1492
|
-
"gameOver": game.
|
|
1493
|
-
"gameFinished": game.
|
|
1494
|
-
"gameMazeWin": game.
|
|
1495
|
-
"starting": game.
|
|
1496
|
-
"initialSpeed": game.
|
|
1497
|
-
"speed": game.
|
|
1498
|
-
"offsetFrame": game.
|
|
1447
|
+
"paused": game.gameEngine.paused,
|
|
1448
|
+
"isReseted": game.gameEngine.isReseted,
|
|
1449
|
+
"exited": game.gameEngine.exited,
|
|
1450
|
+
"snakes": copySnakes(game.gameEngine.snakes),
|
|
1451
|
+
"grid": game.gameEngine.grid,
|
|
1452
|
+
"numFruit": game.gameEngine.numFruit,
|
|
1453
|
+
"ticks": game.gameEngine.ticks,
|
|
1454
|
+
"scoreMax": game.gameEngine.scoreMax,
|
|
1455
|
+
"gameOver": game.gameEngine.gameOver,
|
|
1456
|
+
"gameFinished": game.gameEngine.gameFinished,
|
|
1457
|
+
"gameMazeWin": game.gameEngine.gameMazeWin,
|
|
1458
|
+
"starting": game.gameEngine.starting,
|
|
1459
|
+
"initialSpeed": game.gameEngine.initialSpeed,
|
|
1460
|
+
"speed": game.gameEngine.speed,
|
|
1461
|
+
"offsetFrame": game.gameEngine.speed * GameConstants.Setting.TIME_MULTIPLIER,
|
|
1499
1462
|
"confirmReset": false,
|
|
1500
1463
|
"confirmExit": false,
|
|
1501
1464
|
"getInfos": false,
|
|
1502
1465
|
"getInfosGame": false,
|
|
1503
|
-
"errorOccurred": game.
|
|
1466
|
+
"errorOccurred": game.gameEngine.errorOccurred,
|
|
1504
1467
|
"timerToDisplay": config.enableMaxTimeGame ? (config.maxTimeGame - (Date.now() - game.timeStart)) / 1000 : -1,
|
|
1505
|
-
"countBeforePlay": game.
|
|
1506
|
-
"aiStuck": game.
|
|
1507
|
-
"precAiStuck": false
|
|
1468
|
+
"countBeforePlay": game.gameEngine.countBeforePlay,
|
|
1469
|
+
"aiStuck": game.gameEngine.aiStuck,
|
|
1470
|
+
"precAiStuck": false,
|
|
1471
|
+
"enablePause": game.gameEngine.enablePause,
|
|
1472
|
+
"enableRetry": game.gameEngine.enableRetry,
|
|
1473
|
+
"progressiveSpeed": game.gameEngine.progressiveSpeed
|
|
1508
1474
|
});
|
|
1509
1475
|
} else {
|
|
1510
1476
|
socket.emit("init", {
|
|
1511
|
-
"enablePause": game.
|
|
1512
|
-
"enableRetry": game.
|
|
1513
|
-
"progressiveSpeed": game.
|
|
1514
|
-
"offsetFrame": game.
|
|
1477
|
+
"enablePause": game.gameEngine.enablePause,
|
|
1478
|
+
"enableRetry": game.gameEngine.enableRetry,
|
|
1479
|
+
"progressiveSpeed": game.gameEngine.progressiveSpeed,
|
|
1480
|
+
"offsetFrame": game.gameEngine.speed * GameConstants.Setting.TIME_MULTIPLIER
|
|
1515
1481
|
});
|
|
1516
1482
|
}
|
|
1517
1483
|
|
|
@@ -1584,7 +1550,7 @@ io.on("connection", function(socket) {
|
|
|
1584
1550
|
success: false,
|
|
1585
1551
|
errorCode: GameConstants.Error.ROOM_ALREADY_JOINED
|
|
1586
1552
|
});
|
|
1587
|
-
} else if(Player.containsTokenAllGames(token) || Player.containsIdAllGames(socket.id)) {
|
|
1553
|
+
} else if(Player.containsTokenAllGames(token, games) || Player.containsIdAllGames(socket.id, games)) {
|
|
1588
1554
|
socket.emit("join-room", {
|
|
1589
1555
|
success: false,
|
|
1590
1556
|
errorCode: GameConstants.Error.ALREADY_CREATED_ROOM
|
|
@@ -1597,6 +1563,6 @@ io.on("connection", function(socket) {
|
|
|
1597
1563
|
});
|
|
1598
1564
|
});
|
|
1599
1565
|
|
|
1600
|
-
http.listen(config.port,
|
|
1566
|
+
http.listen(config.port, () => {
|
|
1601
1567
|
console.log("listening on *:" + config.port);
|
|
1602
1568
|
});
|
package/views/admin.html
CHANGED
|
@@ -24,12 +24,19 @@
|
|
|
24
24
|
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
|
25
25
|
<link href="/css/flat-ui.min.css" rel="stylesheet">
|
|
26
26
|
<link href="/css/main.css" rel="stylesheet">
|
|
27
|
+
<% if(theme === "dark") { %>
|
|
28
|
+
<link href="/css/dark-theme.css" rel="stylesheet">
|
|
29
|
+
<% } %>
|
|
27
30
|
<script src="/js/jquery.min.js"></script>
|
|
28
31
|
<script src="/js/bootstrap.bundle.min.js"></script>
|
|
29
32
|
<% if(enableRecaptcha && publicKey) { %><script src="https://www.google.com/recaptcha/api.js?hl=<%= locale %>" async defer></script><% } %>
|
|
30
33
|
<title>SnakeIA Server</title>
|
|
31
34
|
</head>
|
|
35
|
+
<% if(theme === "dark") { %>
|
|
36
|
+
<body class="text-center dark">
|
|
37
|
+
<% } else { %>
|
|
32
38
|
<body class="text-center">
|
|
39
|
+
<% } %>
|
|
33
40
|
<div class="container">
|
|
34
41
|
<div class="row">
|
|
35
42
|
<div class="col">
|
|
@@ -23,10 +23,17 @@
|
|
|
23
23
|
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
|
24
24
|
<link href="/css/flat-ui.min.css" rel="stylesheet">
|
|
25
25
|
<link href="/css/main.css" rel="stylesheet">
|
|
26
|
+
<% if(theme === "dark") { %>
|
|
27
|
+
<link href="/css/dark-theme.css" rel="stylesheet">
|
|
28
|
+
<% } %>
|
|
26
29
|
<% if(enableRecaptcha && publicKey) { %><script src="https://www.google.com/recaptcha/api.js?hl=<%= locale %>" async defer></script><% } %>
|
|
27
30
|
<title>SnakeIA Server</title>
|
|
28
31
|
</head>
|
|
32
|
+
<% if(theme === "dark") { %>
|
|
33
|
+
<body class="text-center remove-padding dark">
|
|
34
|
+
<% } else { %>
|
|
29
35
|
<body class="text-center remove-padding">
|
|
36
|
+
<% } %>
|
|
30
37
|
<div class="container">
|
|
31
38
|
<% if(authent) { %>
|
|
32
39
|
<h3><%= __("alreadyAuthentified") %></h3>
|
package/views/banned.html
CHANGED
|
@@ -23,9 +23,16 @@
|
|
|
23
23
|
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
|
24
24
|
<link href="/css/flat-ui.min.css" rel="stylesheet">
|
|
25
25
|
<link href="/css/main.css" rel="stylesheet">
|
|
26
|
+
<% if(theme === "dark") { %>
|
|
27
|
+
<link href="/css/dark-theme.css" rel="stylesheet">
|
|
28
|
+
<% } %>
|
|
26
29
|
<title>SnakeIA Server</title>
|
|
27
30
|
</head>
|
|
31
|
+
<% if(theme === "dark") { %>
|
|
32
|
+
<body class="text-center dark">
|
|
33
|
+
<% } else { %>
|
|
28
34
|
<body class="text-center">
|
|
35
|
+
<% } %>
|
|
29
36
|
<div class="container">
|
|
30
37
|
<div class="row">
|
|
31
38
|
<div class="col">
|