import React, { useState, useEffect } from 'react'; import Link from 'next/link'; import copy from 'copy-to-clipboard'; import protobuf from 'protobufjs'; import { useWaku, useContentPair, useLightPush, useStoreMessages, useFilterMessages, } from '@waku/react'; import { message } from '@waku/core'; import Loading from './Loading'; const ChatMessage = new protobuf.Type('ChatMessage') .add(new protobuf.Field('timestamp', 1, 'uint64')) .add(new protobuf.Field('sender', 2, 'string')) .add(new protobuf.Field('message', 3, 'string')); export default function Room(props) { const { node } = useWaku(); const [nodeStart, setNodeStart] = useState(false); const [move, setMove] = useState(false); const [boxes, setBoxes] = useState({}); const [player, setPlayer] = useState(false); const [opponentJoined, setOpponentJoined] = useState(null); const [winner, setWinner] = useState(null); const [winningPattern, setWinningPattern] = useState(null); const { decoder, encoder } = useContentPair(); const { messages: storeMessages } = useStoreMessages({ node, decoder, }); const { messages: filterMessages } = useFilterMessages({ node, decoder }); const { push } = useLightPush({ node, encoder }); async function sendMessage(sender, message) { const protoMessage = ChatMessage.create({ timestamp: Date.now(), sender, message, }); const serialisedMessage = ChatMessage.encode(protoMessage).finish(); const timestamp = new Date(); await push({ payload: serialisedMessage, timestamp, }); console.log('MESSAGE PUSHED'); } function decodeMessage(wakuMessage) { if (!wakuMessage.payload) return; const { timestamp, sender, message } = ChatMessage.decode(wakuMessage.payload); if (!timestamp || !sender || !message) return; const time = new Date(); time.setTime(Number(timestamp)); return { message, timestamp: time, sender, timestampInt: wakuMessage.timestamp, }; } useEffect(() => { if (node !== undefined) { if (player === false) { const p = sessionStorage.getItem('roomId') == props.room && sessionStorage.getItem('player') == 'x' ? 'x' : 'o'; setPlayer(p); if (p === 'o') { sendMessage('o', 'joined'); } } setNodeStart(true); } }, [node]); useEffect(() => { let messages = storeMessages.concat(filterMessages); let b = {}; let o = false; messages = messages.map((message) => decodeMessage(message)); messages.forEach((message) => { if (message.message === 'joined') { o = true; return; } if (message.message === 'winner') { return; } b = { ...b, [message.message]: message.sender }; }); const winningCombinations = [ ['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9'], ['1', '5', '9'], ['3', '5', '7'], ]; let winner = null; let temp = null; let winningPattern = null; winningCombinations.forEach((combination) => { if (winner !== null) { return; } for (let [i, c] of combination.entries()) { if (b[c] === undefined) { temp = null; break; } else { if (temp === null) { temp = b[c]; continue; } else { if (temp === b[c]) { if (i === 2) { winner = temp; winningPattern = combination; } continue; } } } } }); setWinner(winner); setWinningPattern(winningPattern); setOpponentJoined(o); setBoxes(b); }, [storeMessages, filterMessages]); if (!nodeStart || !player || opponentJoined === null) { return ; } function handlePlay(i) { if (opponentJoined === false) { alert('Opponent is yet to join!'); return; } if (boxes[i] !== undefined) { alert('Already played!'); return; } if (Object.keys(boxes).length % 2 === 0) { if (player === 'o') { alert("Opponent's turn"); } else { sendMessage('x', i); setBoxes({ ...boxes, i: 'x' }); } } else { if (player === 'x') { alert("Opponent's turn"); } else { sendMessage('o', i); setBoxes({ ...boxes, i: 'o' }); } } } function renderBoxes() { let boxElements = []; for (let i = 1; i < 10; i += 1) { if (boxes[i] === undefined) { boxElements.push(
handlePlay(i.toString())} className='w-20 h-20 border-2 border-white flex items-center justify-center text-2xl text-white' >
); } else { if (boxes[i] === 'x') { boxElements.push(
X
); } else { boxElements.push(
O
); } } } return
{boxElements}
; } return (

Waku status : active

Peers : {node?.libp2p?.getPeers()?.length ?? '-'}

Game URL

https://waku-xo.vercel.app/game/{props.room}

{!opponentJoined && 'Waiting for opponent to join'} {winner == null && opponentJoined && (Object.keys(boxes).length % 2 === 0 ? player === 'x' ? 'Your turn' : "Opponent's turn" : player === 'o' ? 'Your turn' : "Opponent's turn")} {winner != null && (winner === 'x' ? 'X is winner' : 'O is winner')}

{ !winner &&
{renderBoxes()}
}
); }