Adapting your game

If you've built your multiplayer game using Godot's High-Level Multiplayer API or the MultiplayerSynchronizer and MultiplayerSpawner nodes, along with the ENetMultiplayerPeer, it's pretty easy to adapt it to run as a dedicated server on the W4 Cloud!

Configure dedicated server support in W4GD

Dedicated server support in W4GD is disabled by default, so that your project doesn't use the resources on an unused feature.

To enable it in the Godot editor:

  1. Open Project > Project Settings... in the main menu

  2. Enable Advanced Settings if you haven't already:

    Screenshot of the advanced settings toggle in Project Settings
  3. Scroll down to W 4 Games and select Game Server:

    Screenshot of the Game Server settings section under W 4 Games in Project Settings
  4. Check the Enabled checkbox:

    Screenshot of the Enabled setting checked

There are a few other settings here that you may want to configure as well:

Health Check Interval

How often (in seconds) to ping Agones, in order to let it know the server is healthy, or to retry any failed requests.

Player Join Timeout

How long to wait (in seconds) for players to join the server, before deciding the match is "ready" or "failed".

This will lead to either the match_ready or match_failed signals to be emitted.

Minimum Players

If fewer than this number of players join a match before the Player Join Timeout, then a match is considered "failed".

Auto Shutdown on Match Failure

If enabled, the server will automatically shutdown if the match has "failed".

Running in "Game Server mode"

Your game will need to be able to detect that it's running as a Game Server in the W4 Cloud and then switch to a "Game Server mode".

For example, your main scene could include setup code like:

# Default game server port. Can be any number between 1024 and 49151, inclusive.
const DEFAULT_PORT = 10567

# Maximum number of players.
const MAX_PEERS = 4

func _ready():
    if W4GD.game_server.is_server():
        # We're running as a game server!
        setup_gameserver()

func setup_gameserver():
    W4GD.game_server.match_ready.connect(self._on_match_ready)

    # Start listening for connections on an arbitrary port.
    var peer = ENetMultiplayerPeer.new()
    peer.create_server(DEFAULT_PORT, MAX_PEERS)
    multiplayer.set_multiplayer_peer(peer)

    # Mark this server as ready, so Agones can allocate it to a match.
    W4GD.game_server.set_server_state(W4GD.game_server.ServerState.READY)

func _on_match_ready():
    # All the players have connected!
    var players = W4GD.game_server.get_players()

    # Get the lobby properties (which you may have used to store settings for this match).
    var lobby_props = W4GD.game_server.get_server().get_lobby_properties()

    # Once everything is ready, start the match!
    start_match()

Once the match has finished, you need to tell Agones that it's time to shutdown this Game Server:

W4GD.game_server.set_server_state(W4GD.game_server.ServerState.SHUTDOWN)

Depending on how your Fleet is configured and how many other Game Servers currently exist, a new Game Server may be launched to replace this one, or Agones may wait until player demand has increased.

Connecting to the server

Next, you'll need to update the "client mode" of your game to connect to the Game Server.

After creating or joining a lobby, you need to wait for a "server ticket" to be issued for that lobby. The server ticket includes the IP and port of the Game Server to connect to, as well as a secret password that grants the current player permission to connect.

If the lobby isn't a WebRTC lobby, then a server ticket will automatically be issued as soon as the lobby enters the SEALED state.

var lobby

func create_lobby():
    # Get the list of available game server clusters (regions)
    var cluster_list = await W4GD.matchmaker.get_cluster_list().async()
    # Get the result as an array
    var clusters : Array = cluster_list.as_array()
    var result = await W4GD.matchmaker.create_lobby(
        W4GD.matchmaker.LobbyType.DEDICATED_SERVER,
        {
            # Specify in which region the game will take place
            cluster = clusters.front()
        }
    ).async()
    if result.is_error():
        print("ERROR: ", result.message)
        return

    lobby = result.get_data()

    # Wait for a server ticket.
    lobby.received_server_ticket.connect(_on_received_server_ticket)

func seal_lobby():
    # After enough players have joined, this function can be triggered by the lobby
    # creator to seal the lobby and trigger the server ticket to be created.

    lobby.state = W4GD.matchmaker.LobbyState.SEALED

    var result = await lobby.save()
    if result.is_error():
        print("ERROR: ", result.message)
        return

func _on_received_server_ticket(server_ticket):
    # Initializes the client with the given player ID and secret.
    W4GD.game_server.start_client(W4GD.get_identity().get_uid(), server_ticket.secret)

    # Connects to the IP and port of the allocated Game Server.
    var peer = ENetMultiplayerPeer.new()
    peer.create_client(server_ticket.ip, server_ticket.port)
    multiplayer.set_multiplayer_peer(peer)