Hej. Tuż przed świętami natknąłem się na dziwny problem z moją aplikcją, który ze względu na wolny czas chciałem dzisiaj rozwiązać i niestety chyba poniosłem porażkę bo brakuje mi już pomysłów i nie mam pojęcia co jest nie tak... Otóż jakiś miesiąc temu wpadłem na pomysł napisania wieloosobowej gry w karty typu multiplayer. Chciałem lekko zakozaczyć i użyć technologii których wciąż się uczę. Oczywiście cały system oparłem na platformie Node.js plus protokół WebSocket a mianowicie bibliotekę Socket.IO. Back-end napisany w czystym JS ale jak już wspomiałem chciałem zakozaczyć i do front-endu użyłem Reacta. Jak do tej pory wszystko ładnie ze sobą działało - chciażby sam prymitywny czat działa normalnie ale jak już przyszła pora na rozpoczęcie gry i rozdanie kart wszystkim graczom - aplikacja wysypuje się. Po zbadaniu przyczyny okazuje się, że każdy gracz po otrzymaniu odpowiednich wiadomości z obiektami i tablicami zawierającymi niezbędne dane potrzebne do rozpoczęcia gry są PUSTE i React próbuje zmapować chociażby talię kart (oczywiście dla każdego gracza inną) na podstawie pustych danych... Na froncie mam coś takiego:
function App() {
const [playingRooms, setPlayingRooms] = useState([]);
const [playersElapsedTime, setPlayersElapsedTime] = useState([]);
useEffect(() => {
socket.on('start-game', (data) => {
console.log(data);
setPlayingRooms(data.playingRooms);
setPlayersElapsedTime(data.playersElapsedTime);
setStartGameAlertClass('hidden');
console.log(playingRooms);
console.log(playersElapsedTime);
//replacePlayers();
});
}, []);
function startGame() {
socket.emit('start-game', {playingRoomId: ownPlayingRoomId});
}
}
return (
// jsx...
);
export default App;
No i tak wygląda konsola w przeglądarce po rozpocząciu gry (wywołaniu funkcji startGame) - jak widać dane zostały wyemitowane do klientów przez serwer ale później po sprawdzeniu danych stanu Reacta są puste:
Odkomentowując linię //replacePlayers(), która umiejscawia graczy na ekranie wraz z ich kartami, React krzyczy:
No tak jakby po nadejściu wiadomości WebSocket dane stanu React Hooks były przywracane do pierwotnej postaci z nieznanej przyczyny (bo nigdzie indziej ich nie zmieniam). Może ktoś coś podpowie?
PS. Tak na marginesie dołączam jeszcze fragment back-endu w Node:
socket.on('start-game', (data) => {
time = Date.now();
let playingRoomId = parseInt(data.playingRoomId);
let playerId = parseInt(playingRooms[playingRoomId].players.find(player => player.socketId === socket.id).playerId);
let loginName = playingRooms[playingRoomId].players.find(player => player.socketId === socket.id).loginName.toString();
let randomCardsDeck = [];
playersElapsedTime = [];
for (let loop = playingRooms[playingRoomId].lowestCard; loop <= 14; loop++) {
for (let loop2 = 0; loop2 <= 3; loop2++) {
randomCardsDeck.push([loop, loop2]);
}
}
let cardsAmount = randomCardsDeck.length;
let randomNumber = 0;
let temp;
while (cardsAmount--) {
randomNumber = Math.floor(Math.random() * (cardsAmount + 1));
temp = randomCardsDeck[cardsAmount];
randomCardsDeck[cardsAmount] = randomCardsDeck[randomNumber];
randomCardsDeck[randomNumber] = temp;
}
let cardsDeck = [];
let ownCardsDeck = [];
let socketId;
for (let loop = 0; loop < 6; loop++) {
playingRooms[playingRoomId].players.forEach(player => {
if (typeof cardsDeck[player.playerId] === 'undefined') {
cardsDeck[player.playerId] = [];
}
cardsDeck[player.playerId].push(randomCardsDeck.pop());
});
}
playingRooms[playingRoomId].players.forEach(player => {
ownCardsDeck = [];
playersCardsDecks.push({playingRoomId: playingRoomId, playerId: player.playerId, cardsDeck: cardsDeck[player.playerId]});
playingRooms[playingRoomId].players.find(player2 => player2.playerId === player.playerId).cardsAmount = cardsDeck[player.playerId].length;
playersElapsedTime.push({playingRoomId: playingRoomId, playerId: player.playerId, time: playingRooms[playingRoomId].durationTime});
for (let loop = 0; loop < cardsDeck[player.playerId].length; loop++) {
cardsDeck[player.playerId][loop][2] = false;
ownCardsDeck = cardsDeck[player.playerId];
}
socketId = playingRooms[playingRoomId].players.find(player2 => player2.playerId === player.playerId).socketId;
io.to(socketId).emit('own-cards-deck', {ownCardsDeck: ownCardsDeck});
});
io.in(playingRoomId).emit('start-game', {playingRooms: playingRooms, playersElapsedTime: playersElapsedTime});
console.log(currentTime(new Date(time)) + ' - Klient o nazwie użytkownika ' + loginName + ' rozpoczął grę w pokoju nr ' + (playingRoomId + 1));
});