added nakama provider using nakama package
This commit is contained in:
@@ -1,52 +1,99 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
import Board from "./Board";
|
||||
|
||||
export default function TicTacToe() {
|
||||
const [board, setBoard] = useState(Array(9).fill(null));
|
||||
const [xIsNext, setXIsNext] = useState(true);
|
||||
const [username, setUsername] = useState("");
|
||||
const [matchId, setMatchId] = useState("");
|
||||
|
||||
const winner = calculateWinner(board);
|
||||
const [board, setBoard] = useState<string[][]>([
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
["", "", ""]
|
||||
]);
|
||||
const [turn, setTurn] = useState<number>(0);
|
||||
const [winner, setWinner] = useState<string | null>(null);
|
||||
|
||||
function handleSquareClick(i: number) {
|
||||
if (board[i] || winner) return;
|
||||
const {
|
||||
loginOrRegister,
|
||||
joinMatchmaker,
|
||||
joinMatch,
|
||||
onMatchData,
|
||||
socket,
|
||||
sendMatchData
|
||||
} = useNakama();
|
||||
|
||||
const newBoard = board.slice();
|
||||
newBoard[i] = xIsNext ? "X" : "O";
|
||||
// ------------------------------------------
|
||||
// CONNECT
|
||||
// ------------------------------------------
|
||||
async function connect() {
|
||||
await loginOrRegister(username);
|
||||
|
||||
setBoard(newBoard);
|
||||
setXIsNext(!xIsNext);
|
||||
// Match data listener
|
||||
onMatchData((msg) => {
|
||||
console.log("[Match Data]", msg);
|
||||
|
||||
if (msg.opCode === 2) {
|
||||
const state = msg.data;
|
||||
|
||||
setBoard(state.board);
|
||||
setTurn(state.turn);
|
||||
setWinner(state.winner || null);
|
||||
}
|
||||
});
|
||||
|
||||
// When matchmaker finds a match
|
||||
socket!.onmatchmakermatched = async (matched) => {
|
||||
console.log("Matched:", matched);
|
||||
|
||||
const fullMatchId = matched.match_id;
|
||||
setMatchId(fullMatchId);
|
||||
|
||||
await joinMatch(fullMatchId);
|
||||
};
|
||||
}
|
||||
|
||||
function reset() {
|
||||
setBoard(Array(9).fill(null));
|
||||
setXIsNext(true);
|
||||
// ------------------------------------------
|
||||
// SEND A MOVE
|
||||
// ------------------------------------------
|
||||
function handleCellClick(row: number, col: number) {
|
||||
if (!matchId) return;
|
||||
|
||||
sendMatchData(matchId, 1, { row, col }); // OpMove=1
|
||||
}
|
||||
|
||||
const status = winner
|
||||
? `Winner: ${winner}`
|
||||
: `Next player: ${xIsNext ? "X" : "O"}`;
|
||||
// ------------------------------------------
|
||||
// MATCHMAKING
|
||||
// ------------------------------------------
|
||||
async function startQueue() {
|
||||
const ticket = await joinMatchmaker("classic");
|
||||
console.log("Queued:", ticket);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="game-container">
|
||||
<h1>Tic Tac Toe</h1>
|
||||
<div className="status">{status}</div>
|
||||
<Board squares={board} onClick={handleSquareClick} />
|
||||
<button className="reset-btn" onClick={reset}>Reset</button>
|
||||
<div>
|
||||
<h1>Tic Tac Toe Multiplayer</h1>
|
||||
|
||||
{!matchId && (
|
||||
<>
|
||||
<input
|
||||
placeholder="username/device ID"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
/>
|
||||
<button onClick={connect}>Connect</button>
|
||||
<button onClick={startQueue}>Join Matchmaking</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{matchId && (
|
||||
<Board
|
||||
board={board}
|
||||
turn={turn}
|
||||
winner={winner}
|
||||
onCellClick={handleCellClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// --- winner logic ---
|
||||
function calculateWinner(sq: any[]) {
|
||||
const lines = [
|
||||
[0,1,2],[3,4,5],[6,7,8],
|
||||
[0,3,6],[1,4,7],[2,5,8],
|
||||
[0,4,8],[2,4,6]
|
||||
];
|
||||
for (let [a,b,c] of lines) {
|
||||
if (sq[a] && sq[a] === sq[b] && sq[a] === sq[c]) {
|
||||
return sq[a];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user