Starlight-30036225 / ChessTCP

FILLMELATER
0 stars 0 forks source link

Disconnect and Reconnect handling #38

Closed Starlight-30036225 closed 7 months ago

Starlight-30036225 commented 7 months ago

Up until now, there has been no checks for when a client disconnects from the game. This can often cause errors that I have elected to ignore until now.

Now, When a clientcloses the GUI it sends a disconnect packet to the server. If the client disconnects, it will remove all references to it across the room and roommap first to avoid memory leaks. `` room.connections--;

    if (handler == room.whitePlayer) {room.whitePlayer = null;}
    if (handler == room.blackPlayer) {room.blackPlayer = null;}

    roomMap.remove(handler);    //removes all references to the disconnecting player

``

Then if the client was a spectator, no changes need to be made to the room. Otherwise, the game needs to be paused. If both players have left, the room will be closed. Otherwise, the other player will be notified that their opponent has left.

``

if (room.whitePlayer != null && room.blackPlayer != null) {return;} //the player that left was a spectator,doesn't matter

    //tells other clients that this player has left
    for (ConnectionHandler CH:
            clients.stream()
                    .filter(CH -> roomMap.get(CH) == room)
                    .toList()) {
        CH.sendMessage(PacketHeader.DISCONNECT, CloseRoom? "END": "CON"); //If no players, close room, otherwise keep open till both players leave
        if (CloseRoom) {
            roomMap.remove(CH);}
    }

``

image

By keeping the room open, and giving the remaining player the option to stay, it effective facilitates reconnecting.

Starlight-30036225 commented 7 months ago

Some changes need to be made to the joining code to allow players to rejoin.

``

   if(room.connections == 2 && !room.started) {        //Waits until both core players have joined to start game
        for (ConnectionHandler CH:
                clients.stream()
                        .filter(CH -> roomMap.get(CH) == room)
                        .toList()) {
            CH.sendMessage(PacketHeader.BOARD_STATE, "WHITE" + room.loadNotationFromMap());
            room.started = true;

        }
    } else if (room.started){        //Anyone who joins after the game has started, even a rejoin, doesn't have to wait
        handler.sendMessage(PacketHeader.BOARD_STATE, (room.white? "WHITE" : "BLACK") + room.loadNotationFromMap());
    }

``

Originally this code only checked if there were two players before passing the rest of the players to spectators. However, now players can leave and rejoin, the two player condition can be met twice, which can cause complications. Furthermore, a player can have more than 2 clients connected without the game necceserily being playable. If there is a spectator watching, and one of the two players leaves, there are 2+ players in the room but is unplayable, hence the code needing to be changed.