const express = require('express'); const database = require('./database'); const cardGen = require('./cardGen'); const roomMod = require('./roomMod'); const app = express(); const http = require('http').Server(app); const port = process.env.PORT || 3000; const io = require('socket.io')(http); // util is what nodejs uses for console.log, but has a depth of 2 set // so console.logs show [Array]/[Object] instead of useful info. // This can be overridden console.log(util.inspect(LOGDATA, true, 4, true)) // 4 being new depth, true (last one) is to show colours const util = require('util') app.use(express.static(__dirname + '/public')); http.listen(port, () => console.log('listening on port ' + port)); database.connect(); io.on('connection', onConnection); // Variables let numRooms = 0; let numRoomsToPreGen = 1; const maxRooms = 3; const maxPlayersPerRoom = 2; const maxSpectatorsPerRoom = 0; // All the room //let data = []; // Normal array let data = {}; // Object array (this one for returning to player, and JSON stringify while keeping named ids) let roomData = {}; for (let roomId = 1; roomId <= numRoomsToPreGen; roomId++) { // Never have more rooms than max rooms!!! if(numRooms > maxRooms){ break; } createRoom(roomId); } function onConnection(socket){ console.log('+ User connected'); console.log(''); socket.on('requestRooms', function(filter) { requestRooms(socket, filter); }); socket.on('requestJoinRoom', function(playerName, roomId) { requestJoinRoom(socket, playerName, roomId); }); socket.on('requestCreateRoom', function(playerName) { requestCreateRoom(socket, playerName); }); } function requestRooms(socket, filter){ console.log('+ requestRooms recieved'); console.log('- filter: '+filter); let response = getRooms(filter, dump = true); io.to(socket.id).emit('returnRooms', response); console.log(''); } function getRooms(filter = 'all', dump = false){ console.log('+ getRooms'); let response = { random: 'randomStuff', roomData: roomData, }; if(dump){ console.log(response); console.log(''); } return response; } function requestCreateRoom(socket, playerName){ console.log('+ createRoom recieved'); console.log('- requested by: '+playerName); response = createRoom(roomId = false, dump = true); io.to(socket.id).emit('returnCreateRoom', response); if(response.success){ let response = getRooms(filter = 'all', dump = true); io.to(socket.id).emit('returnRooms', response); } console.log(''); } function createRoom(roomId = false, dump = true){ let roomName = false; if(roomId == false){ roomId = numRooms + 1; } console.log(roomId); let response = { success: false, message: 'No idea bossman' }; // Max room limit reached console.log(numRooms); console.log(maxRooms); if(numRooms >= maxRooms){ console.log('- Room limit reached'); response = { success: false, message: 'No space '+numRooms+' out of '+maxRooms+' created.' }; // Create room }else{ console.log('- Creating room') let room = {}; room['id'] = roomId; room['name'] = 'Room:'+room['id']; roomName = room['name']; room['password'] = ''; room['timeout'] = {}; room['timeout']['s'] = 10; room['people'] = 0; room['playerIds'] = {}; //room['deck'] = []; //room['turn'] = 0; // Removed players for now, players may be seperate // and back-end only with an assoc. to current room //let players = {}; //for (let j = 0; j < maxPlayersPerRoom; j++) { //let p = {}; //p['id'] = 0; //p['name'] = ""; //p['hand'] = {}; //players[j] = p; //} //room['players'] = players; roomData[roomId] = room; numRooms = numRooms + 1; response = { success: true, message: 'Room Created: '+roomName, }; } if(dump){ console.log(response); console.log(''); } return response; } // TODO: break into requestJoinRoom, and JoinRoom? // Maybe not needed here? As won't be done via backend? // TODO: Need a 'leave room'/disconnect function requestJoinRoom(socket, playerName, roomId){ console.log('+ requestJoinRoom recieved'); let room = roomData[roomId]; // Add socket for playerName so that players in room get // responses, etc. from the room (something like that) // Add player to socket object, so it can be referred to // as each socket is individual to a player, but rooms need to // emit to multiple players. These .player can be used in loops // https://socket.io/docs/v4/rooms/ // https://stackoverflow.com/a/18096649 socket.playerId = playerName; if(room === undefined){ io.to(socket.id).emit('responseRoom', 'error'); console.log('>> Room does not exist'); } let roomName = 'Room_' + roomId; let people = room['people']; // people = io.sockets.adapter.rooms[roomId].length; // This gets the sockets in the room (i.e. the players) //console.log(util.inspect(io.sockets.adapter.rooms, true, 4, true)) //console.log('- people(socket: '+io.sockets.adapter.rooms[player]+')'); //console.log('- maxPlayersPerRoom: '+maxPlayersPerRoom); if(isUserInRoom(playerName, roomId)){ console.log('Already in room'); return false; } if (people < maxPlayersPerRoom) { // Update people in room count people = room['people'] += 1; // Add playerId to room (playerName for now while Ids don't exist TODO) room['playerIds'][playerName] = playerName; // https://socket.io/docs/v4/rooms/ // https://stackoverflow.com/a/25028953 socket.join(roomId); // https://stackoverflow.com/a/25028953 //console.log(util.inspect(io.sockets.adapter.rooms.get(roomId), true, 4, true)) /* let clients = io.sockets.adapter.rooms.get(roomId); let numClients = clients ? clients.size : 0; for (const clientId of clients) { //this is the socket of each client in the room. const clientSocket = io.sockets.sockets.get(clientId); console.log(clientSocket.playerId); // The playerId set beggining of func. } */ console.log('>> User ' + playerName + ' connected on ' + roomName + ' (' + (people) + '/' + maxPlayersPerRoom + ')'); // Joined room (emit to the player that just joined) io.to(socket.id).emit('responseJoinRoom', roomName); if (people >= maxPlayersPerRoom) { console.log('- starting game'); // startGame for room startGame(roomId); } } } // Will need to be different to playerName in future (in case dupes) // would use playerId TODO function isUserInRoom(playerName, roomId){ if(playerName in roomData[roomId]['playerIds']){ return true; } return false; } function startGame(roomId){ console.log('>> Room: ' + roomId + ': Requesting game...'); let people = roomData[roomId].players; /* try { //people = io.sockets.adapter.rooms.get(roomId).size; } catch (e) { console.log('>> Room: ' + roomId + ': No people here...'); return; } */ // For now, if there's 2 people only. Will need changing for // 3v1, 5v1, 2v2, etc... let response = {success: false, message: 'Failed requestStartGame() server.js'}; if(people < maxPlayersPerRoom){ console.log('Too few people'); } console.log('>> Room: ' + roomId + ': Starting'); // https://stackoverflow.com/a/25028953 //console.log(util.inspect(io.sockets.adapter.rooms.get(roomId), true, 4, true)) let clients = io.sockets.adapter.rooms.get(roomId); /* for (const clientId of clients) { //this is the socket of each client in the room. const clientSocket = io.sockets.sockets.get(clientId); console.log(clientSocket.playerId); // The playerId set in requestJoin // Just so I know how to access stuff in future. console.log(roomData[roomId].playerIds[clientSocket.playerId] + 'is in the game'); } */ // This should return the deck data, etc. for each client // ideally only returning the items that the user can/should // see i.e. shouldn't give them the inDeck card list just a counter // shouldn't have opponent card data/their hand shouldn't be flipped roomMod.roomGeneration().then(data => { response.success = true; response.message = data; // Each player then gets the roomGeneration stuff for (const clientId of clients) { const clientSocket = io.sockets.sockets.get(clientId); console.log('>> responseStartGame: '+clientSocket.playerId); // Emit to client socket io.to(clientSocket.id).emit('responseStartGame', response); } }) .catch(err => { response.message = err; // Each player then gets the error message for (const clientId of clients) { const clientSocket = io.sockets.sockets.get(clientId); // Emit to client socket io.to(clientSocket.id).emit('responseStartGame', err); } }); } // Then do functions like this? function shuffleDeck(roomId, playerId){ }