Starlight-30036225 / ChessTCP

FILLMELATER
0 stars 0 forks source link

Allow users to chose rooms #32

Closed Starlight-30036225 closed 5 months ago

Starlight-30036225 commented 5 months ago

I want users to be given the option between creating a new room, or joining an already created room.

This is likely going to be quite troublesome.

My expectation is that after connection, a user will need to be placed in an identified pool where they wait to be assigned a room.

They will only be assigned a room when they send a specific packet detailing the room they want. This means the welcome packet will need to be adjusted to send information of all rooms.

This is going to be a pain, but lets begin.

Starlight-30036225 commented 5 months ago

The first step is for the server to pass all open rooms as options to the client. This is done by extracting the list of rooms from the map. Then from this list, the number of players and whether the room is locked or not is added to the infomation for each room. Then a composite string is send to the client.

``

    List<GameMaster> AllRooms = roomMap.values().stream().toList();

    String infoString = "";
    for (GameMaster temproom:
            AllRooms) {
        String temp;
        temp = temproom.Connections + "_" + (Objects.equals(temproom.password, "") ? 'Y' : 'N');
        infoString += temp;
    }
    if (infoString.equals("")) {infoString = "...";}
    CH.sendMessage(PacketHeader.ROOM_INFO, infoString);

``

Then this infomation needs to be decyphered by the client. Each room is in the format numberofplayers_LockedStatus (2_Y)

``

    int selection;
    System.out.println("1: Create new room");
    if (!Objects.equals(Rooms, "...")) {
        for (int i = 0; i < Rooms.length() / 3; i++) {
            System.out.println((i + 2) + ": " + Rooms.charAt(i * 3) + " Connected - " +
                    (Rooms.charAt((i * 3) + 2) == (char) 'Y' ? "Locked" : "Open"));
        }
    }

`` This prints to the console, which is ugly but for now its better than faffing with a fresh window for such a quick choice.

`` if (selection == 1){

            System.out.println("Enter password, leave black for no password:");
            Password = sc.nextLine();
        } else if (Rooms.charAt(((selection - 2) * 3) + 2) == (char) 'Y'){
            System.out.println("Enter password");
            Password = sc.nextLine();
        }
        sendMessage(PacketHeader.ROOM_INFO, selection - 1 + Password);

``

Then the client returns its selection to the server.

There is some error checking inbetween but this is the important stuff

Now to allow the server to assign rooms correctly.

Starlight-30036225 commented 5 months ago

The server will take the clients choice, and either create a room to accomidate, or add them to a already created room.

``

private void AssignClientRoom(ConnectionHandler CH) {
     String RoomSelection = CH.readNextString();
    GameMaster room = null;
    int selection = RoomSelection.charAt(0) - 48;
    if (selection == 0){
        room = new GameMaster();
    }
    else{
        room = roomMap.values().stream().toList().get(selection - 1);
    }

    if (!testmode) {
        if (room.WhitePlayer == null) {
            room.WhitePlayer = CH;
            roomMap.put(CH, room);
            CH.sendMessage(PacketHeader.WELCOME, "WHITE");
        } else if (room.BlackPlayer == null) {
            room.BlackPlayer = CH;
            roomMap.put(CH, room);
            CH.sendMessage(PacketHeader.WELCOME, "BLACK");
        }
    }
    room.Connections++;
    CH.sendMessage(PacketHeader.BOARD_STATE, room.LoadNotationFromMap());

}

``

For now, this ignores passwords and spectators. But this should work fine.

Starlight-30036225 commented 5 months ago

The first player to connect is not given many choices image I will let it create a new room

lets add a new client now a room has been made image

Thats not meant to be locked, but thats an easy fix.

image

Nice!

Starlight-30036225 commented 5 months ago

I added an additional check to allow users to put passwords on servers. I need to add encryption on both sides to protect the password.

But here is the password system so far:

When the player selects their room, if they create one and make it locked or attempt to join a locked room, they will be prompted to input a password. This is placed at the end of the string when send.

`` if (selection == 1){

            System.out.println("Enter password, leave black for no password:");
            Password = sc.nextLine();
        } else if (Rooms.charAt(((selection - 2) * 3) + 2) == (char) 'Y'){
            System.out.println("Enter password");
            Password = sc.nextLine();
        }

``

When the server receives the client choice, if the string is longer than one character it knows there is a password attached. Which is then either assigned to the newly created room, or checked against the rooms existing password.

`` if (selection == 0){ room = new GameMaster(); room.password = password; } else{ room = roomMap.values().stream().distinct().toList().get(selection - 1); if (!Objects.equals(room.password, password)){ Handler.sendMessage(PacketHeader.MISC, "Incorrect Password."); SendRoomInfo(Handler); return; } }

``

I created a new packet, the misc packet. Which just sends infomation to be printed to the console. For now it is only used to tell players they inputted the wrong password.

Now i need to add encryption