added nakama provider using nakama package

This commit is contained in:
2025-11-27 16:51:06 +05:30
parent c6c9d10476
commit 4565c4b33a
6 changed files with 331 additions and 50 deletions

View File

@@ -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;
}