diff options
-rw-r--r-- | src/components/App.js | 3 | ||||
-rw-r--r-- | src/components/GamemodeChooser.js | 1 | ||||
-rw-r--r-- | src/components/MultiplayerGrid.js | 38 | ||||
-rw-r--r-- | src/components/MultiplayerMenu.js | 45 | ||||
-rw-r--r-- | src/server/index.js | 48 |
5 files changed, 116 insertions, 19 deletions
diff --git a/src/components/App.js b/src/components/App.js index db5af1b..5b13230 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -33,6 +33,7 @@ const App = () => { const [showMessageBox, setShowMessageBox] = useState(false); const [message, setMessage] = useState(""); const [isHost, setIsHost] = useState(false); + const [joinCode, setJoinCode] = useState(); return gameStarted ? ( <> @@ -61,6 +62,7 @@ const App = () => { setScoreO={setScoreO} setMessage={setMessage} setShowMessage={setShowMessageBox} + joinCode={joinCode} /> : <Grid turn={turn} setTurn={setTurn} @@ -81,6 +83,7 @@ const App = () => { setMultiplayer={setMultiplayer} setGameStarted={setGameStarted} setIsHost={setIsHost} + setJoinCode={setJoinCode} /> <Footer/> </> diff --git a/src/components/GamemodeChooser.js b/src/components/GamemodeChooser.js index 91010e4..6b2e985 100644 --- a/src/components/GamemodeChooser.js +++ b/src/components/GamemodeChooser.js @@ -47,6 +47,7 @@ const GamemodeChooser = (props) => { <MultiplayerMenu setIsHost={props.setIsHost} setGameStarted={props.setGameStarted} + setJoinCode={props.setJoinCode} /> <div className={"GamemodeButton"} onClick={() => { diff --git a/src/components/MultiplayerGrid.js b/src/components/MultiplayerGrid.js index 88a8259..d7eae36 100644 --- a/src/components/MultiplayerGrid.js +++ b/src/components/MultiplayerGrid.js @@ -26,11 +26,43 @@ const socket = io("http://localhost:5000"); const MultiplayerGrid = (props) => { // 0 is O, 1 is X, 2 is blank const [board, setBoard] = useState([2,2,2,2,2,2,2,2,2]); + const turn = props.turn; + const isHost = props.isHost; + const joinCode = props.joinCode; + const setMessage = props.setMessage; + const setShowMessage = props.setShowMessage; + + // host/join room + useEffect(() => { + if (isHost) { + socket.emit("host"); + + socket.on("broadcast code", (code) => { + setMessage(`Game Code: ${code}`); + setShowMessage(true); + }); + + socket.on("player joined", () => { + setMessage("Opponent Joined") + setShowMessage(true) + setTimeout(() => setShowMessage(false), 3000) + }) + } else { + socket.emit("join", joinCode); + + // error if room doesn't exist + socket.on("join failed", () => { + setMessage("Error: room not found") + setShowMessage(true) + setTimeout(() => window.location.reload(), 3000) + }); + } + }, [isHost, setMessage, setShowMessage, joinCode]); const getBoard = (index) => { // if it's not your turn you can't play - if ((turn === 0) === props.isHost) return; + if ((turn === 0) === isHost) return; const newBoard = board.slice(0, index).concat(turn).concat(board.slice(index+1, 9)); socket.emit("update-remote-data", { @@ -42,10 +74,10 @@ const MultiplayerGrid = (props) => { } const endGame = (data) => { - props.setMessage( + setMessage( `${data.winner === "Data" ? "" : "WINNER: "}${data.winner}` ); - props.setShowMessage(true); + setShowMessage(true); props.setScoreX(data.scoreX); props.setScoreO(data.scoreO); diff --git a/src/components/MultiplayerMenu.js b/src/components/MultiplayerMenu.js index 1dfe9dd..aa77507 100644 --- a/src/components/MultiplayerMenu.js +++ b/src/components/MultiplayerMenu.js @@ -15,24 +15,45 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import React from 'react'; +import React, { useState } from 'react'; import './style.css'; const MultiplayerMenu = (props) => { + const [showCodeInput, setShowCodeInput] = useState(false) + const [joinCode, setJoinCode] = useState(""); + return ( <div className={"MultiplayerMenu"}> - <div className={"GamemodeButton"} onClick={() => { - props.setIsHost(true); - props.setGameStarted(true); - }}> - HOST GAME - </div> + {showCodeInput + ? <> + <input type="text" placeholder={"ENTER CODE"} + className={"GamemodeButton"} onChange={ + (event) => setJoinCode(event.target.value) + } + /> + + <div className={"GamemodeButton"} onClick={() => { + props.setGameStarted(true); + props.setJoinCode(joinCode); + }}> + START + </div> + </> + : <> + <div className={"GamemodeButton"} onClick={() => { + props.setIsHost(true); + props.setGameStarted(true); + }}> + HOST GAME + </div> - <div className={"GamemodeButton"} onClick={() => { - props.setGameStarted(true); - }}> - JOIN GAME - </div> + <div className={"GamemodeButton"} onClick={() => { + setShowCodeInput(true); + }}> + JOIN GAME + </div> + </> + } </div> ); } diff --git a/src/server/index.js b/src/server/index.js index 2799805..a5aa97f 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -3,15 +3,37 @@ const app = express(); const http = require('http').Server(app); const path = require('path'); -// const io = require('socket.io')(http); const io = require("socket.io")(http, { cors: { - origin: ["http://localhost:5000", "http://localhost:3000"], + origin: [ + "http://localhost:5000", + "http://localhost:3000", + "https://mikunonaka-tic-tac-toe.herokuapp.com", + "http://mikunonaka-tic-tac-toe.herokuapp.com" + ], "Access-Control-Allow-Origin": "*", methods: ["GET", "POST"] } }); +// check if room exists +const checkCode = (code) => { + const connectedSockets = []; + io.sockets.sockets.forEach( + (i) => connectedSockets.push(i) + ); + + // returns true if room exists + return connectedSockets.some( + (i) => Array.from(i.rooms)[1] === code + ); +} + +// generate new room code +// also checks for duplicates +const getCode = (code = `${Math.floor(1000 + Math.random() * 9000)}`) => + checkCode(code) ? getCode : code; + const allEqual = (arr) => arr.includes(2) ? false : arr.every(i => i === arr[0]) @@ -38,7 +60,25 @@ const getScore = (winner, scoreX, scoreO, board) => ({ }) io.on('connection', (socket) => { + socket.on('host', () => { + const code = getCode(); + socket.join(code); + io.to(code).emit('broadcast code', code); + }); + + socket.on('join', (code) => { + if (checkCode(code)) { + socket.join(code); + io.to(code).emit('player joined'); + } else { + // error if room doesn't exist + socket.emit('join failed') + } + }); + socket.on('update-remote-data', (data) => { + const room = Array.from(socket.rooms)[1] + if (data.board.includes(0) || data.board.includes(1)) { const rows = getRows(data.board); const winner = (rows.some((i) => allEqual(i)) @@ -47,13 +87,13 @@ io.on('connection', (socket) => { ) ? data.turn : 2; const score = getScore(winner, data.scoreX, data.scoreO, data.board) - io.emit('update-client-data', { + io.to(room).emit('update-client-data', { board: data.board, turn: score.winner ? data.turn : (data.turn === 0 ? 1 : 0), score: score }); - score.winner && io.emit('update-winner', score) + score.winner && io.to(room).emit('update-winner', score) }; }); }); |