-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
170 lines (147 loc) · 7.1 KB
/
app.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
/* Requirements */
var express = require("express");
var http = require("http");
var websocket = require("ws");
var ejs = require("ejs");
var cookieParser = require('cookie-parser');
/* Local code requirements */
var Game = require("./game");
var gameStats = require("./stats");
var messages = require("./public/javascripts/messages");
/* Start Express app with specified command argument port */
var port = process.argv[2];
var app = express();
app.use(cookieParser());
// routes setup
var indexRouter = require("./routes/index.js")(app, gameStats);
/* EJS view engine set up and directory */
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
// --- WebSockets ---
var websockets = []; // array keeping track of websockets
var connectionID = 0; // keep track of next unique WebSocket Connection ID
var currentGame = new Game(gameStats.gamesInitialized++); // keep track of current game
// Server Creation
var server = http.createServer(app).listen(process.env.PORT || 3000); // create server on port
const wss = new websocket.Server( {server} ); // create WebSocket server
// Listen for incoming WebSocket connections
wss.on("connection", function connection(ws) {
let connection = ws; // reference connection to ws
connection.id = connectionID++; // assign unique ID, increment it for use for next connections
let playerType = currentGame.addPlayer(connection); // true for White, false for Black
websockets[connection.id] = currentGame; // assign game to connection ID in WebSockets array
gameStats.activeGamers++; // increase active gamers count on connection
// debug
console.log("Player %s placed in game %s as %s", connection.id, currentGame.id, (playerType ? "White" : "Black"));
// inform the client about the pieces that will be controlled by the client (constructing the message accordingly beforehand)
let playerTypeJSON = messages.cloneMessage(messages.O_PLAYER_TYPE);
playerTypeJSON.data = playerType;
connection.send(JSON.stringify(playerTypeJSON));
if (!playerType) // Second Player joined
{
// Start Game & Send Message to both sockets
var startMSG = JSON.stringify(messages.O_START_GAME);
currentGame.p1.send(startMSG);
connection.send(startMSG);
// Start next new Game to put Players in
currentGame = new Game(gameStats.gamesInitialized++);
gameStats.ongoingGames++;
}
else // First Player joined
{
// Inform the client that we're waiting for another Player
connection.send(JSON.stringify(messages.O_INITIALIZE_GAME));
}
var socketGame = websockets[connection.id];
// Close WebSocket
connection.on("close", function (code)
{ gameStats.activeGamers--;
console.log(connection.id + " disconnected");
if(!socketGame.hasTwoPlayers)
{
socketGame.p1=null;
}
else if (code == "1001")
{
if (socketGame.p1.readyState != 3 || socketGame.p2.readyState != 3) // there exists one player that is still connected
{
// Decrement Ongoig Games count
gameStats.ongoingGames--;
// Check if socket has been closed, and if not, send them the Game Aborted message
if(socketGame.p1.readyState != 3)
{
socketGame.p1.send(JSON.stringify(messages.O_GAME_ABORTED));
}
else if (socketGame.p2.readyState != 3)
{
socketGame.p2.send(JSON.stringify(messages.O_GAME_ABORTED));
}
}
}
});
// Get incoming messages from WebSockets
connection.on("message", function incoming(message)
{
// Parse message
var incomingMSG = JSON.parse(message);
// Receive Click Event from WebSocket
if (incomingMSG.type === messages.O_TILE_CLICK_BY.type)
{
// Generate click response according to game state
var clickResponse = socketGame.gameState.getClick(incomingMSG.tile, incomingMSG.player, incomingMSG.selected);
// Click response is valid
if (clickResponse != null)
{
if (clickResponse.type === messages.O_MOVE_PIECE.type) // Moved piece successfully
{
// send standard blank O_SELECT_PIECE the message to the client that executed the move (effectively deselecting the piece)
connection.send(JSON.stringify(messages.O_SELECT_PIECE));
// Update board for both players
var checkInfo = socketGame.gameState.newTurn();
if(checkInfo.length>1){
var playerCheckStatus = checkInfo[0];
var checkmateStatus = checkInfo[1];
} else{
var playerCheckStatus = null;
var checkmateStatus = checkInfo[0];
}
// If a piece is moved successfully, switch the turn
socketGame.p1.send(JSON.stringify(clickResponse));
socketGame.p2.send(JSON.stringify(clickResponse));
if(playerCheckStatus!=null){
if(playerCheckStatus.data==true)
socketGame.p1.send(JSON.stringify(playerCheckStatus));
else socketGame.p2.send(JSON.stringify(playerCheckStatus));
}
if(checkmateStatus.data!=null){
// For simplicity, commenting this out for now
// gameStats.ongoingGames--;
gameStats.gamesCompleted++;
if(checkmateStatus.data==1){
// If a checkmate is detected, send the corresponding messages to each player
if(checkmateStatus.player==true){
socketGame.p1.send(JSON.stringify(checkmateStatus));
checkmateStatus.data+=1;
socketGame.p2.send(JSON.stringify(checkmateStatus));
} else {
socketGame.p2.send(JSON.stringify(checkmateStatus));
checkmateStatus.data+=1;
socketGame.p1.send(JSON.stringify(checkmateStatus));
}
}
if(checkmateStatus.data==0){
// If a stalemate is detected, send the same message to both of the players
socketGame.p1.send(JSON.stringify(checkmateStatus));
socketGame.p2.send(JSON.stringify(checkmateStatus));
}
}
}
else // Select piece
{
// Send response to client containing info required for piece selection/move invalidity
connection.send(JSON.stringify(clickResponse));
}
}
}
});
});