/**
* Handles all socket client events including server connection and listener initialization.
* @class SocketClientHandler
*/
import io from "socket.io-client";
import { GameState } from '@/stores/GameState';
import GameView from "@/views/GameView.vue";
class SocketClientHandler {
/**
* Attempt to connect current client to socket server.
* @param {string} socketServer Hosted socket server address
* @param {string} testServer Local socket server address
* @param {boolean} inProduction determines whether to connect to hosted or local server
* @param {object} gameData All game data from game view component
* @returns Socket client data object
*/
connectSocketServer(socketServer, testServer, inProduction, gameData) {
let socket = this.initSocketConnection(socketServer, testServer, inProduction)
if (gameData.isHost)
this.createLobby(socket, gameData)
else
socket.emit('join-room', gameData.roomCodeStr, GameState().currentUser, gameData.isHost);
this.initSocketListeners(socket, gameData)
return socket
}
/**
* Initialize connection to socket server.
* @param {string} socketServer Hosted socket server address
* @param {string} testServer Local socket server address
* @param {boolean} inProduction determines whether to connect to hosted or local server
*/
initSocketConnection(socketServer, testServer, inProduction) {
// Establish connection to the WebSocket server
try {
if (inProduction)
return io(socketServer);
else
return io("http://" + testServer + ":3001");
} catch (error) {
console.log("initSocketConnection error: " + error)
}
}
/**
* Create new lobby. If host playing is true, add player to game data
* @param {object} socket Client socket data used to receive and send socket server data
* @param {object} gameData All game data from game view component
*/
createLobby(socket, gameData) {
try {
// Create new lobby, if host is not playing send null for user to add to player data
if (gameData.isHostPlaying) {
gameData.players.push(GameState().currentUser)
gameData.mappedPlayerData.set(GameState().currentUser, {
currentGuess: "",
currentGuessImagePath: "",
score: 0
})
socket.emit("create-new-lobby", gameData.numRounds, gameData.maxPlayers, gameData.players, GameState().currentUser);
}
else
socket.emit("create-new-lobby", gameData.numRounds, gameData.maxPlayers, gameData.players, null);
} catch (error) {
console.log("createLobby error: " + error)
}
}
/**
* Initialize client-side socket listener events
* @param {object} socket
* @param {object} gameData
*/
initSocketListeners(socket, gameData) {
// Listen for player joining
socket.on("add-player", (user, value) => {
gameData.mappedPlayerData.set(user, value)
console.log(gameData.mappedPlayerData)
})
// Listen for player leaving
socket.on("remove-player", (user) => {
gameData.mappedPlayerData.delete(user)
console.log(GameView.mappedPlayerData)
})
// Listen for host to start of new round
socket.on("start-game", () => {
gameData.gameStarted = true;
gameData.gameEnded = false;
})
// Listen for end of game
socket.on("end-game", () => {
gameData.gameStarted = false;
gameData.gameEnded = true;
gameData.currentRound = 0;
})
// Listen for host to play game again
socket.on("play-again", () => {
console.log(' ON PLAY AGAIN ')
gameData.gameStarted = false;
gameData.gameEnded = false;
})
// Listen for "everyone guessed correct"
socket.on("all-guessed-correct", (message) => {
gameData.triggerAllGuessedCorrectPopup();
})
// Listen for "timer ran out"
socket.on("timer-ran-out", (message) => {
gameData.triggerTimeRanOutPopup();
})
// Listen for new player list
socket.on("update-player-list", (newPlayers) => {
gameData.players = newPlayers;
})
// Listen for new guesses
socket.on("update-user-guess", ({
user,
guess,
imagePath,
score
}) => {
gameData.mappedPlayerData.get(user).currentGuess = guess;
gameData.mappedPlayerData.get(user).currentGuessImagePath = imagePath;
gameData.mappedPlayerData.get(user).score = score;
console.log('data ' + user + ' ' + guess + ' ' + imagePath + ' ' + score)
// If the guess is correct, display it
if (guess == gameData.promptWord && guess){
//console.log(`${gameData.promptWord} is the prompt and ${guess} is the guess.`)
console.log(`${user} guessed correctly!`)
}
})
// Listen for new lobby code
socket.on("update-lobby-code", (newRoomCode) => {
console.log("Updating lobby code: ", newRoomCode);
gameData.roomCodeStr = newRoomCode;
// Fix: Convert string digits to numbers properly
gameData.roomCodeArr = newRoomCode.split('').map(digit => parseInt(digit, 10));
// Connect user to lobby
socket.emit('join-room', gameData.roomCodeStr, GameState().currentUser, gameData.isHost);
});
// Listen for score reset (to zero)
socket.on("reset-scores", ({user, score}) => {
gameData.mappedPlayerData.get(user).score = score;
})
// Listen for max players for lobby
socket.on("update-max-players", (updateMaxPlayers) => {
gameData.maxPlayers = updateMaxPlayers;
})
// Listen for new round count
socket.on("update-round", (updateRound) => {
gameData.currentRound = updateRound;
console.log(`currentRound: ${gameData.currentRound}`)
})
// Listen for number of rounds
socket.on("update-num-rounds", (updateNumRounds) => {
gameData.numRounds = updateNumRounds;
console.log(`currentRound: ${gameData.numRounds}`)
})
// Listen for new drawer
socket.on("update-drawer", (drawer) => {
gameData.drawer = drawer; // Add this line to store the current drawer
if (GameState().currentUser == drawer)
gameData.isDrawer = true;
else
gameData.isDrawer = false;
})
// Listen for new prompt
socket.on("update-prompt", (updatePrompt, path) => {
gameData.promptWord = updatePrompt.word;
console.log('PROMPT WORD: ', gameData.promptWord);
gameData.promptImgPath = path;
gameData.isGuessCorrect = false;
})
// Listen for update to current user
socket.on("update-user", (user) => {
GameState().currentUser = user;
})
// Listen for the player count from the server
socket.on("player-count-update", (count) => {
gameData.playerCount = count;
//console.log("Updated player count:", count);
});
// Listen for broadcasted initial drawing data
socket.on("cast-draw-init", (x, y, draw_color, draw_width) => {
gameData.context = document.getElementById("canvas").getContext("2d");
gameData.context.strokeStyle = draw_color;
gameData.context.lineWidth = draw_width;
gameData.context.beginPath();
gameData.context.moveTo(x, y);
});
// Listen for broadcasted drawing data
socket.on("cast-draw", (x, y) => {
gameData.context.lineTo(x, y);
gameData.context.lineCap = "round";
gameData.context.lineJoin = "round";
gameData.context.stroke();
});
// Listen for broadcasted final drawing data
socket.on("cast-draw-end", () => {
gameData.context.closePath();
});
// Listen for broadcasted clear canvas
socket.on("cast-draw-clear", () => {
gameData.context = document.getElementById("canvas").getContext("2d");
gameData.context.fillStyle = "white";
gameData.context.clearRect(0, 0, document.getElementById("canvas").width, document.getElementById("canvas").height);
});
// Listen for broadcasted undo canvas
socket.on("cast-draw-undo", (previousState) => {
gameData.context.putImageData(previousState, 0, 0);
});
// Listen for broadcasted timer update from server
socket.on("timer-update", (serverTime) => {
gameData.roundTimer = serverTime;
});
//Listen for message sending player back to join screen
socket.on("return-to-join-screen", () => {
console.log("redirecting to joinlobby");
GameState.showAvatarTakenError = true;
gameData.$router.push('/joinLobby');
});
}
}
export default SocketClientHandler