Skip to content

How to Use

This page shows practical integration flows for the Godot SDK.

Before you start

You need two things before calling create_instance(...):

  • A deployed template on an Encore Server. The template identifier (often referred to as game_ID, used as template_id in API/SDK calls) is created when that template exists on the server.
  • The URL of that Encore Server, passed to EncoreConfig so the SDK knows where to send requests.

Example client setup:

gdscript
var config = EncoreConfig.new("https://encore.yourcompany.com")
var encore_client = EncoreClient.new(config)
add_child(encore_client)

1) Create a game server instance

gdscript
var instance = await encore_client.create_instance("game_QkMtDm7A2x", {
    "max_players": "10",
    "map_name": "dm_foundry"
})

if instance.is_empty():
    show_error("Failed to create instance")
    return

print("Join code: %s" % instance.user_token)
print("Connect: %s:%d" % [instance.host, instance.port])

Use this flow for the player who is hosting the match.

2) Join by token

gdscript
func join_game(token: String):
    var connection = await encore_client.get_connection_info(token)
    if connection.is_empty():
        show_error("Invalid or expired game code")
        return

    var parts = connection.split(":")
    connect_to_server(parts[0], int(parts[1]))

Use this for invited players who receive a user_token.

3) Pass player-selected options with extra_options

gdscript
func create_match(selected_map: String, selected_mode: String, player_count: int):
    var instance = await encore_client.create_instance("game_QkMtDm7A2x", {
        "map_name": selected_map,
        "game_mode": selected_mode,
        "max_players": str(player_count)
    })

    if instance.is_empty():
        show_error("Could not create match")
        return

    print("Token: %s" % instance.user_token)
    connect_to_server(instance.host, instance.port)

This is the typical client flow: your UI collects match settings (map, mode, player count), then sends them as extra_options on create.

Important:

  • extra_options keys are only accepted if whitelisted in the server template.
  • invalid types (for example max_players = "abc") are rejected by the API.
  • template_id still selects the base server profile; extra_options customize match behavior.

4) Handle errors correctly

SDK methods return empty values on failure:

  • {} for instance lookups/creates
  • [] for template lists
  • "" for connection helpers

Always check return values first, then use signals for detailed handling.

gdscript
const EncoreError = preload("res://addons/encore/client/error.gd")

encore_client.instance_creation_failed.connect(func(error: EncoreError):
    match error.code:
        EncoreError.Code.TEMPLATE_NOT_FOUND:
            show_error("Selected game mode is not available")
        EncoreError.Code.INSTANCE_LIMIT_REACHED:
            show_error("Servers are full, try again shortly")
        EncoreError.Code.NO_PORTS_AVAILABLE:
            show_error("No free game servers right now")
        EncoreError.Code.TIMEOUT:
            show_error("Request timed out")
        _:
            show_error("Create failed: %s" % error.message)
)

5) Useful helper methods

  • create_and_get_connection_info(template_id, extra_options): one-call helper when you only need host:port.
  • get_connection_info(identifier): token/instance-to-connection helper.
  • template_exists(template_id): quick pre-check for template-dependent flows.
  • list_templates(): typically for admin/backoffice tools (requires admin-enabled route on the server).

In many production setups, game clients should not rely on list_templates() because /api/v1/templates is usually admin-protected.

  1. On startup, create one shared EncoreClient node.
  2. Build lobby options in your game UI (or backend config) for map/mode/player settings.
  3. Host flow: create_instance(...), display user_token, connect host.
  4. Join flow: resolve token with get_connection_info(...), then connect.
  5. Centralize error signal handling in one UI/controller node.

You can mix await return checks with centralized signals:

gdscript
const EncoreError = preload("res://addons/encore/client/error.gd")

func _ready():
    encore_client.instance_created.connect(_on_instance_created)
    encore_client.instance_creation_failed.connect(_on_instance_creation_failed)

func _on_instance_created(data: Dictionary) -> void:
    print("Server ready: %s:%d" % [data.get("host"), data.get("port")])

func _on_instance_creation_failed(error: EncoreError) -> void:
    push_error("Create failed: %s" % error.message)

API surface summary

  • create_instance(template_id, extra_options = {}) -> Dictionary
  • get_instance(identifier) -> Dictionary
  • list_templates() -> Array (admin-enabled route)
  • create_and_get_connection_info(template_id, extra_options = {}) -> String
  • get_connection_info(identifier) -> String
  • template_exists(template_id) -> bool

For complete SDK details, refer to sdk/README.md in the repository root.