const express = require('express'); const database = require('./database'); const rooms = require('./rooms'); const gameMod = require('./gameMod'); const app = express(); const http = require('http').Server(app); const port = process.env.PORT || 3000; const io = require('socket.io')(http); global.io = io; // To log the player sockets, so they can be easily referred to // maybe jank, but can't see alternative currently global.playerSocket = {}; global.roomData = {}; // Made global for now, as to not replicate. Maybe sub-optimal? // 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); function onConnection(socket){ console.log('+ User connected'); console.log(''); // Rooms (joining, creating, etc) socket.on('requestRooms', function(filter) { rooms.requestRooms(socket, filter); }); socket.on('requestJoinRoom', function(playerName, roomId) { rooms.requestJoinRoom(socket, playerName, roomId); }); socket.on('requestCreateRoom', function(playerName) { rooms.requestCreateRoom(socket, playerName); }); // Game (actual things relating to the game) // The socket should only be in one game, so socket.on should // do this, but passing room/player anyways as it's how I've written some // roomData bits. TODO: Look if I can do this better... socket.on('passTurn', function(roomId, playerId) { gameMod.passTurn(roomId, playerId); }); socket.on('drawACard', function(roomId, playerId) { gameMod.drawACard(roomId, playerId); }); socket.on('shuffleDeck', function(roomId, playerId) { gameMod.shuffleDeck(roomId, playerId); }); socket.on('playFromHand', function(roomId, playerId, listPosition) { gameMod.playFromHand(roomId, playerId, listPosition); }); socket.on('playManaFromHand', function(roomId, playerId, listPosition) { gameMod.playManaFromHand(roomId, playerId, listPosition); }); socket.on('requestResolveStack', function(roomId, playerId) { gameMod.acceptResolveStack(roomId, playerId); console.log('resolve stack yep yep yep'); }); } global.getPlayerSocketFromRoom = function(playerId, roomId){ return roomData[roomId].playerData[playerId].socketId; } global.sendToEachSocket = function(roomId, responseName, data){ console.log(responseName); let clients = global.io.sockets.adapter.rooms.get(roomId); for (const clientId of clients) { const clientSocket = global.io.sockets.sockets.get(clientId); // Send to a client socket global.io.to(clientSocket.id).emit(responseName, data); } } // Globals for easier clientside alerts/logs, etc. global.socketAlert = function(socket, message, type = 'alert'){ global.io.to(socket).emit( type, {'message': message} ); } // passTurn response for all clients in room // TODO: include spectators when added global.socketResponsePassTurn = function(roomId){ let data = { 'playerTurn': global.roomData[roomId].itemData.component.playerTurn, 'turn': global.roomData[roomId].itemData.component.turn, }; global.sendToEachSocket(roomId, 'responsePassTurn', data); } // Then emit the deckSize and hand size to all the player's sockets // TODO: spectators in future, won't comment about this from now on global.socketResponseDrawCard = function(roomId, playerId){ console.log('>> '+roomData[roomId].playerData[playerId].playerId+' drew card'); global.socketReturnCardCounts(roomId, 'responseDrawCard'); } global.socketReturnCardCounts = function(roomId, responseName = 'responseCardCounts'){ let data = global.roomData[roomId].itemData.component.cardCount; global.sendToEachSocket(roomId, responseName, data); } global.socketResponsePlayerDrewCard = function(roomId, playerId){ global.socketResponsePlayerHandData(roomId, playerId); } global.socketResponsePlayerHandData = function(roomId, playerId){ // This function may be redundant fast, as hand, board, grave, void // anywhere that's visible to one (or both) players will need all the data // sending, so will likely be one function that returns it all? // Could do each thing as their own, and union the data too? global.io.to(global.getPlayerSocketFromRoom(playerId, roomId)).emit( 'responsePlayerDrewCard' ,gameMod.getPlayerHandData(roomId, playerId) ); } global.socketResponseShuffleDeck = function(roomId, playerId, hasShuffled){ global.io.to(global.getPlayerSocketFromRoom(playerId, roomId)).emit( 'responseShuffleDeck' ,[playerId, hasShuffled] ); } global.socketResponseUpdateBoard = function(roomId){ // TODO: Only return the data that's needed, no everything let data = global.roomData[roomId].itemData.component; // Return the data on the board (to both players) // TODO: If card flips/face-downs are to be a thing, only return the cardData, etc. // to the player who's side it's on global.sendToEachSocket(roomId, 'responseUpdateBoard', data); } global.socketResponseUpdateMana = function(roomId){ // TODO: Only return the data that's needed, no everything let data = global.roomData[roomId].itemData.component; global.sendToEachSocket(roomId, 'responseUpdateMana', data); } global.socketResponsePlayFromHand = function(roomId, playerId, cardId){ console.log('>> '+roomData[roomId].playerData[playerId].playerId+' played from hand'); // Return the new cardCounts for hand/deck/grave, etc. global.socketReturnCardCounts(roomId); // Update hand of player that card's hand was played from (using existing logic) global.socketResponsePlayerHandData(roomId, playerId); // Update the board (for both players) global.socketResponseUpdateBoard(roomId); // So the animations can be played with the new cardData (in future) global.sendToEachSocket(roomId, 'responsePlayFromHand', cardId); } global.socketResponsePlayManaFromHand = function(roomId, playerId, cardId){ console.log('>> '+roomData[roomId].playerData[playerId].playerId+' played mana from hand'); // Return the new cardCounts for hand/deck/grave, etc. global.socketReturnCardCounts(roomId); // Update hand of player that card's hand was played from (using existing logic) global.socketResponsePlayerHandData(roomId, playerId); // Update the mana (for both players) global.socketResponseUpdateMana(roomId); // So the animations can be played with the new cardData (in future) //global.sendToEachSocket(roomId, 'responsePlayFromHand', cardId); } global.socketResponsePlayedShield = function(roomId, playerId){ //global.socketReturnCardCounts(roomId, 'responseDrawCard'); // Return playerId of who played a shield so it can be added then animated global.sendToEachSocket(roomId, 'responsePlayedShield', playerId); // Date for shield let data = global.roomData[roomId].itemData.component; global.sendToEachSocket(roomId, 'responseUpdateShield', data); } // Stack global.socketResponseAddToStack = function(roomId){ global.sendToEachSocket(roomId, 'responseAddToStack', 'testData'); } global.socketResponseResolveStack = function(roomId){ global.sendToEachSocket(roomId, 'responseResolveStack', 'testData'); } // TODO: Each player one at a time to prevent just self-chaining 24/7 global.socketGetStackResponse = function(roomId){ // TODO: Return all valid effect triggers/responses to the effect trigger // on the top of the stack, and a 'resolve' option to not trigger anything global.sendToEachSocket(roomId, 'responseGetStackResponse', 'testData'); }