Skip to main content

Setting up Player-based

This is the step-by-step guide for setting up the player-based architecture. For general information about architecture see here. If your game is built using Unity, you can find additional information on how to integrate Idem into your game here.

In the Player-based architecture, each player, or more correctly your game client running on the player's machine, connects to Idem to submit itself to matchmaking. Once a match is found, Idem will spin up a game server on your behalf for the players to play on. For this setup, Idem partners with multiple hosting providers. Additionally, since your game client will connect to Idem directly, we support multiple authentication providers to enable trusted connections.

The following providers are currently supported:

If you don't find the provider of your choice in this list, reach out to match@idem.gg. We are continously growing our partner and provider network and the one you are looking for might alreay be part of it soon.

The default flow for a player-based setup looks like this:

Player-based architecture default flow
Player-based architecture default flow
note

The player-based architecture only supports WebSocket.

🄰 Setup your game-server hosting provider

Go to your hosting provider and set up the code for your game-server. Idem will be calling it through the respective API to launch an instance of your game-server, as soon as a match is found. Specific details on integrating each hosting-provider, including examples, can be found here.

🄱 Select Player-based configuration

Go to the Integration section of the Idem console. There, first select Player-based using the toggle on the top. Then select the hosting provider of your choice and enter the respective data needed to launch the game-server.

You can find details about the integration with each provider on the related pages:

  • Hathora
  • Edgegap
  • i3D
  • Gameye
  • GPortal
  • GameHosting

🄲 Retrieve Join-Code

Switch to the Matchmaker section of the Idem console and copy the Join Code. This will only show if you selected Player-basedin step 🄱. You will need this code to open a WebSocket connection from your game-clients to Idem to submit them for matchmaking.

🄳 Integrate Idem into your game client

Each player's game-client will need to establish a websocket to Idem's API (using the JOIN_CODE obtained in 🄲) and then submit themselves to matchmaking via the WebSocket. Once a match suggestion is found for them, Idem will host a server on your behalf at the hosting provider you set up and then send the connection details to the player via the same WebSocket connection.

The following steps describe what the game-client needs to do step-by-step.

① Open WebSocket connection

First, the game-client needs to open a WebSocket connection to Idem using the following URI:

uri = WEBSOCKET_API_URL/?playerId=PLAYER_ID&code=JOINCODE&authorization=PLAYER_AUTH

WEBSOCKET_API_URL

URL to connect to. Initially, simply take wss://ws.beta.idem.gg. Later you can change this environment, as you take the game from testing to production. See WebSocket for more.

PLAYER_ID

Identifier for the player. If you are planning to use one of our player authentication integrations, refer to the Player authentication documentation to find out which identifier to use. If you don't want to use player authentication, this can be any value as long as it is unique for each player.

JOIN_CODE

Code retrieved in step (c). This code allows Idem to associate your game-client's request with your game. It functions as a basic level of shared authorization. See PLAYER_AUTH below for more details.

PLAYER_AUTH

Initially, use the value Demo. This skips any further authorization. Once you have made yourself familiar with the general setup, we recommend to integrate with a third-party authentication providers (Steam, Firebase, Discord or Custom JWT) to authenticate players in your game client and provide a provider token for authorization when opening the WebSocket connection. This ensures that only authorized players are submitting themselves for matchmaking and that they are using their correct PLAYER_ID.

② Submit the player to the matchmaking queue

Once the WebSocket connection is established, the game-client can enqueue the player via the addPlayerAction. Idem will respond to this with an addPlayerResponse, confirming that the player is now considered by the matchmaking. You can use this information to update the UI to inform the user that the system is now looking for a match for them.

③ Wait for matchFound and inform the player about it

Once a match if found for the player, Idem sends a matchFound message to the game client via the WebSocket. This means a match was found and Idem is now requesting the game server to be hosted by the hosting provider you configured in 🄱.

Message example

{
"action": "matchFound",
"payload": {
"gameId": "1v1",
"matchUuid": "9e6697cd-2271-41bf-9f10-ce7e083e0ed7"
}
}
tip

We strongly recommend to update the UI to inform the user that they have been matched and a game server is now being hosted for them. This gives them a better feeling of progress and avoids them experiencing a longer wait without updates.

info

While waiting, Idem will send a keepAlive message every minute.

A note on players dropping before matchFound message is sent

If the WebSocket connection to any of the clients in a match is interrupted before we can send them the matchFound message, the default behavior is to fail the match. In that case, all clients with a active WebSocket connection receive a requeueRequire message with reason: playerDropped. By this we avoid hosting unnecessary servers on your behalf in cases where it is certain that not all players will show up.

We recommend to implement logic in your client to requeue players automatically if this message is received.

If your game can be played with incomplete teams (this is for example often the case for coop setups where there is only one team) and you prefer to have any game hosted independent of players dropping, this behavior can be easily changed. Just reach out to match@idem.gg.

④ Wait for joinInfo and the join the server

Once Idem receives the join info for the game server from the hosting provider, it will immediately forward that information to the game-client. This comes in form of a joinInfo action. This includes:

  • Information about the hosting provider
  • A standardized connectionInfo object for which we extract information from each hosting provider's custom responses for simple integration
  • A rawProviderInformation object with the relevant information in the respective provider's shape in case you prefer that shape or need access to more advanced information

The general format looks like this:

{
"action": "joinInfo",
"payload": {
// Which hosting provider this data is from.
"providerName": "hathora" | "i3d" | "edgegap" | "gameye" | ...,

// The provider-defined identifier for the deployment/room/server/...
"providerReference": "134098103948013948",

// The core information the game client needs to connect. Standardized among hosting providers.
"connectionInfo": {
// The best "human-friendly" address: Domain if provided, otherwise IP.
// Note that some providers don't respond with any host information immediately but the client needs
// to retrieve it via an endpoint. So this can in some cases be null as well.
// See the provider detail pages for more information.
"host": "abc123.test.edgegap.com",

"ip": "100.10.0.85", // null if no IP is provided.

"domain": "abc123.test.edgegap.com", // null if no domain is provided.

// List of public ports, includes name and protocol if available.
"ports": [
{
"name": "game",
"port": 31669,
"protocol": "udp"
},
{
"name": "web",
"port": 31587,
"protocol": "http"
}
]
},

// Raw response from the provider for advanced usage. See hosting provider pages for details.
"rawProviderInformation": {
...
}
}
}

The concrete shape of the payload depends on the hosting provider. See the relevant hosting provider page for more information.

After Idem has sent the joinInfo to the game clients, the players are also removed from the matchmaking queue. Before this, players are blocked from entering the queue again as no player can be in the matchmaking process twice at the same time.

Once received, the information from the joinInfo should be used to have the game clients connect to the game server.

info

Depending on how you are setting up your game server, it might not be ready to accept connections when the hosting providers reports to Idem that it is running. It is recommended to add some retry logic to the game client in case the server is not ready to accept the game clients connection request immediately.

warning

The Idem matchmaker will launch a server (or the equivalent of the respective provider) on your behalf for each valid match that is created. We strongly recommend to make sure that your server code has logic to correctly shut down when the match is over or if the match does is not played for some reason, e.g. not all players joining ("no show"). Otherwise you might get charged for unnecessary server usage by the hosting provider.

A note on removing players from the queue before being matched

Waiting players are automatically removed from the queue as soon as the WebSocket connection breaks. Hence, the removePlayer action is not used in player-based setup.

Depending on why the WebSocket connection breaks, it might take a second or two for this to be processed by the system. Therefore a game client might get a partyExists... message when trying to submit a player immediately after breaking a previous WebSocket connection. This is expected behavior. Should you consider this a realistic scenario for your game, we recommend to implement a basic retry mechanism.

A note on game hosting failures

Should the game hosting fail ever fail some reason, Idem will send all players a requeueRequired message with the reason: gameHostingFailed. For this requeueRequired message, we recommend to implement logic in your client to requeue players automatically with a maximum retry to avoid infinite loops.

Code sample

This Python code is an example of how to connect your game-client to Idem for a 1v1 game mode. The game-client connects to Idem, and submits a player to the queue. If then another player joins (e.g. by running the code in a separate terminal), Idem generates a match, launches the game-server on your provider, and returns the connection details to both game-clients. This is an easy way to see the end-to-end process fromt the game-client side.

We recommend using this code to get first experience with the WebSocket interactions.

Setup

  • JOIN_CODE : Enter the join-code you can obtain from the console in the "matchmaker" tab.
  • SERVER : When joining the matchmaking, a list of viable server(-regions) is attached to each player (see Latency and region). The matchmaker will only match those players with each other that have at least on server in common. When a match is found, a server is launched in that region. For this sample, ensure you put servers into the list that your hosting provider allows.
player_based_sample.py
import json
import sys
import random

import websockets
import websockets.sync.client as client

WEBSOCKET_API_URL = "wss://ws.beta.idem.gg"
GAME_ID = "1v1"
JOIN_CODE = "9cf9dc78-49c0-4965b-ab2c-5b257d7eeab34"

SERVER = ['eu-west','somewhere'] # pick a server (-region) here that is supported by your game-hoster


def sync_websocket_client(code: str, player_id: str, player_auth: str):
uri = f"{WEBSOCKET_API_URL}/?playerId={player_id}&code={code}&authorization={player_auth}"

try:
with client.connect(uri) as websocket:
print(f"Connected to {WEBSOCKET_API_URL}")

## 1. Adding player to matchmaking queue
print("\n-- 1. Adding player to matchmaking queue --")

# Send player to matchmaking queue
request = {
"action": "addPlayer",
"payload": {
"players": [
{"playerId": player_id, "servers": SERVER}
],
"partyName": player_id,
"gameId": GAME_ID,
},
}
websocket.send(json.dumps(request))
print(f"Sent add_player request: {request}")


## 2. Waiting for Idem to confirm having received the message
print("\n-- 2. Waiting for Idem to confirm the player being added to matchmaking queue --")

# Listening
response = json.loads(websocket.recv())

# Check for error, e.g. if player with same id already in the queue
assert 'error' not in response, f"Error: {response['error']['code']}, {response['error']['message']}"

# Receive acknowledgement of player
print(f"Received add_player acknowledgement: {response}")


## 3. Waiting for a second player to join, match to be created, server to be launched
print("\n-- 3. Waiting for second player to join, be matched, server to be launched --")

# Wait for other players
while True:
response = json.loads(websocket.recv())
if response['action']=='keepAlive':
print('Received Keep-Alive ping')
else:
print(f"Received game room info: {response}")
break

except websockets.exceptions.ConnectionClosed as e:
print(f"Connection closed: {e}")
except Exception as e:
if str(e)=="server rejected WebSocket connection: HTTP 500":
print("Check the join-code. The server rejected the join-code")
else:
print(e)

if __name__ == "__main__":
# read the player_id from the command line
player_id = sys.argv[1] if len(sys.argv) > 1 and sys.argv[1]!='-f' else "player"+str(random.randint(1, 10000))
sync_websocket_client(JOIN_CODE, player_id, "Demo")

🄴 Integrate Idem into your game-server

The last step is to integrate Idem into your game-server. To faciliate this, Idem is passing environment variables to the server as part of the hosting request to the server hosting provider independent of the specific provider. These are:

idemGameId

The game mode the server was hosted for. Examples include:

  • 1v1
  • 2v2
  • 3-coop
Depending on your setup, you might want to use this to run the correct game mode on your server.

idemMatchUuid

The unique identifier for the match. You will need to reference this when confirming the match at the beginning and reporting back the match result to Idem when the match is finished.

idemTeams

An array including all teams in the match with their players. The shape of this is an "array of arrays of player objects". Each player object contains the playerId and the player's rating. Examples:

1v1 match
[
[{ "playerId": "player1", "rating": 1350.5 }],
[{ "playerId": "player2", "rating": 1420.3 }]
]
2v2 match
[
[
{ "playerId": "player1", "rating": 1590.4 },
{ "playerId": "player2", "rating": 1510.2 }
],
[
{ "playerId": "player3", "rating": 1625.9 },
{ "playerId": "player4", "rating": 1480.7 }
]
]
3-coop match
[
[
{ "playerId": "player1", "rating": 1775.3 },
{ "playerId": "player2", "rating": 1840.6 },
{ "playerId": "player3", "rating": 1715.8 }
]
]

Required integration

There are three required steps for integrating Idem into your game-server using the first two variables:

1. Confirming the match

To allow Idem to correctly manage the matches lifecycle, the game server needs to send a confirmation to Idem once the match has started. This is step ⑤ in the graphic on top of the page.

For this, the server needs to open a WebSocket connection and authorize using username and password as described in the API documentation. After opening a WebSocket connection, the server needs to send the confirmMatchAction with the idemGameId as gameId and the idemMatchUuid as the matchId.

tip

If you prefer using a REST call for this, you can also use the relevant REST API endpoint.

2. Reporting the match result

After the game is completed, the game server can report the outcome of the game to Idem with the completeMatchAction. This is step ⑥ in the graphic on top of the page.

For this, the WebSocket connection created for confirming the match can be reused or a new one can be opened if the previous one was already closed. Similar to the confirmMatchAction the message should use the idemGameId as gameId and the idemMatchUuid as the matchId.

You also need to pass values for server (string) and gameLength (float). If this data is not relevant to you in the future, you can pass any non-null value.

Additionally, the outcome of the match needs to be provided as a teams object where each team is listed with the rank (starting from 0), and an array of players with their score. If your game does not have a scores, just pass 1 for each player.

For a 1v1 game the message for the completeMatchAction could for example look like this:

{
"action": "updateMatchCompleted",
"messageId": null,
"payload": {
"gameId": "1v1",
"matchId": "ba60813a-f7ea-4a8f-84c6-c7faf4d415ae",
"server": "test",
"gameLength": 10.0,
"teams": [
{
"rank": 0,
"players": [
{
"playerId": "player1",
"score": 1.0
}
]
},
{
"rank": 1,
"players": [
{
"playerId": "player2",
"score": 1.0
}
]
}
]
}
}

For more options, refer to the API documentation or reach out to us at match@idem.gg.

tip

If you prefer using a REST call for this, you can also use the relevant REST API endpoint.

3. Reporting if the match is not completed for some reason

If the match is not completed for some reason, you need to fail it in order to allow the players to requeue to the matchmaking. Some examples for why this might be necessary are:

  • Not all players are joining (see "Checking teams and players" below)
  • There is some error on the game server

For this, the server needs to open a WebSocket connection and authorize using username and password as described in the API documentation. After opening a WebSocket connection, the server needs to send the failMatchAction with the idemGameId as gameId and the idemMatchUuid as the matchId.

info

Requeueing players directly via the failMatchAction is not supported for player-based setups. Therefore all players in the match need to be passed in the remove parameter of the failMatchAction.

If for some reason the game server realizes a problem immediately, the match can also be failed before confirming it (see 1.). Based on the behavior of the failMatchAction, this will also remove the players from the matchmaking queue and allow them to requeue.

tip

If you prefer using a REST call for this, you can also use the relevant REST API endpoint.

Optional integration

In addition to the required integration, the information provided by Idem in the form of enviornment variables enables two more scenarios that might not be relevant for all customers.

1. Starting the right game mode

If your game supports different game modes, your game-server can use the idemGameId variable to start the right game mode for upcoming match. This removes the need to infer this in some way from the clients connecting.

2. Checking teams and players

The idemTeams variable provides a list of teams in the match with the respetive players. You can leverage this to check if various things related to the players and teams. For example:

  • Is a specific player trying to join the server expected and should be admitted?
  • Are players in the right teams? (As this is important since the matchmaking considers each player's skill to decide in which team to put them.)
  • Have all players joined so that the game can start?