Joining a game round

In this part, we will define:

  • How to join a game.

  • How to start a game round from a lobby. This will only be possible for the person creating the lobby.

The code for connecting to the server is almost identical to the usual Godot networking code.

Do you remember the unfinished _join_game() function from earlier? Navigate to the function definition and complete it with the following code:

## Appends a client to a W4 session and opens a connection.
##
## Only called from clients.
func _join_game(ip_or_address: String, port: int, ticket_password: String) -> void:
    # Once again, we use this to retrieve the player nickname across game sessions.
    var player_name := ProfileData.restore().player_name

    # This function returns the player's unique ID, which we need to start the corresponding client.
    var player_id: String = W4GD.get_identity().get_uid()

    # This function sets up the player's client connection with the running game instance in the W4 cloud.
    # It internally sets callbacks in case the player gets disconnected or their authentication fails.
    # This function must be called before creating an ENetMultiplayerPeer, which we do below.
    W4GD.game_server.start_client(player_id, ticket_password, {player_name = player_name})

    # This code establishes a connection and communication channel for this player.
    # In the previous part, we established the server. When joining the game round, we need to establish the client connection.
    var peer := ENetMultiplayerPeer.new()
    peer.create_client(ip_or_address, port)
    multiplayer.multiplayer_peer = peer

A few things of note:

  • We're once again using our ProfileData resource to store and retrieve a user name. This is not necessary; it's just a convenience to save and pass around player names.

  • To start the client, we must pass the player_id, as obtained from authentication, and the ticket password. This ticket is obtained from W4 once the matchmaker finds a matching lobby.

We can now add the function that allows the lobby creator to start the game. In our project, this happens when the lobby creator clicks the "start" button in the lobby's user interface.

../../_images/lobby-start.png
## Starts a game round.
func start_match() -> bool:
    last_error = ""
    if not _lobby:
        assert(_lobby, "Lobby was not created before calling start_match().")
        return false

    # We seal the lobby, which prevents more players from joining it.
    _lobby.state = W4GD.matchmaker.LobbyState.SEALED

    # This synchronizes the lobby's state with W4.
    var result = await _lobby.save().async()
    if result.is_error():
        last_error = "Unable to seal the lobby"
        return false
    return true

This sets the lobby to SEALED, meaning that no one can enter the lobby anymore. Then, we synchronize the lobby with W4.

Once the lobby is synchronized, W4 will send a ticket to all clients, which will trigger a call to _join_game(). This "ticket" is sent by W4 after sealing the lobby and passed to every player via the Lobby object's received_server_ticket signal.

We connected to this signal when we set up the matchmaking and lobby code.

And that's our network flow!

In the next part, we'll complete the networking code setup to allow us to export the game and playtest online.