Sessions and joining
How a player joins a session, what the game receives on the web and the desktop, how friends join and invite each other, and how a game uses neo_net.
On this page
A session is one running copy of a game that a group of players share; the platform calls it a server in its interface. This page follows a player from Play to being in the session with everyone else, then shows what a game author does with the engine's networking library, neo_net.
Joining a session#
When a player presses Play on a game page, the platform calls SessionService.Join with the game's id and the player's platform (web, macos, windows or linux). It picks a session:
- A specific session, when the player chose Join on a server in the game page's Servers tab, followed a friend, or opened an invite link. The join fails if that session is full.
- Otherwise, the fullest open session that still has room, on the game's live version. Fewer, fuller sessions are more fun to play in.
- A new session when none has room.
Matchmaking never puts a player in a session with someone who blocked them or whom they blocked, nor into a session whose host doesn't let them join (Who can join my games in the host's privacy settings). A Solo game always gets a new session for each player.
Only players who may see the game can join: anyone for a public game, and only you and your testers for a private or draft one. A game also needs a live version with a build for the player's device; otherwise the join fails with "this experience isn't available on platform yet".
What Join returns#
| Field | What it is |
|---|---|
session_id | The session the player is in. |
game_token | A token scoped to this session, game and version, valid for an hour. It is the only credential the game holds. |
hosting_tier | solo, peer, edge or dedicated. See Multiplayer. |
host_user_id | The session's host, for player-hosted sessions. |
connect_url | The game relay to connect to. Empty for a Solo game. |
content_url | The build for the player's device. |
members | Who is in the session. |
While a player is in a session, the platform's player sends a heartbeat every 30 seconds. A player who misses heartbeats for 90 seconds is taken out of the session, and an empty session closes. Leaving the game (or closing the page) leaves the session.
See the sessions API reference for every call and field.
How the game gets the session#
On the web#
The platform's Play overlay opens the game's web build in a frame and puts the session in the address fragment, which never reaches a server:
index.html#neo_token=<game_token>&neo_session=<session_id>&neo_api=<API>&neo_tier=<hosting_tier>&neo_relay=<connect_url>&neo_user=<user_id>&neo_title=<title>&neo_autostart=1Values are percent-encoded, and games ignore keys they don't use. neo_autostart=1 starts the game as soon as its content has downloaded.
On the desktop#
The NEO Platform desktop client starts the game's packaged desktop build with the session in its environment:
| Variable | Value |
|---|---|
NEO_RELAY | The relay (connect_url). |
NEO_GAME_TOKEN | The game token. |
NEO_SESSION_ID | The session. |
NEO_EXPERIENCE_ID | The game. |
NEO_HOSTING_TIER | The hosting tier. |
NEO_PLATFORM_API | The API the game may call with the token. |
NEO_USER_ID | The player (optional). |
Connecting to the relay#
The game connects to the relay with its game token. The relay checks the token, puts the player in the session's room and replies with a welcome: the player's id in the room, the players already there and which relay node serves the room. The player's platform account comes from the token, so a game can't claim to be someone else.
Playing together#
From the game page and the Play overlay, players can:
- Join a friend. The Servers tab lists open servers with "n of m players" and the headshots of friends in each; Join goes straight in. Friends who hide their online status aren't shown.
- Invite friends. In the Play overlay, open the players panel (the player count, or Players and invites in the menu) and choose Invite next to a friend. The friend gets an invite they can join directly.
- Share a link. Copy invite link in the menu copies the game's address with the session in it.
The players panel shows everyone in the session with Host, Friend and Guest tags.
Using neo_net in your game#
Games made from the GASP template already do all of this: the gameplay kit sends the player's state and shows everyone else as characters, with no code from you. A game with its own player character uses neo_net directly:
app.add_plugins(neo_net::NetPlugin);
// every frame, the local player's state (metres, radians, m/s; None until spawned):
local.0 = Some(neo_net::LocalState { position, yaw, velocity, mode });
// everyone else, sampled 100 ms in the past (interpolated, briefly extrapolated):
for (id, r) in &remotes.0 { if let Some(s) = r.current { /* show r.info.username at s.position */ } }mode is a byte your game defines (the template packs its gait, crouch, strafe and in-the-air flags into it). The plugin reads the session from the address fragment or the environment; without one it stays offline and the game is single player.
| Resource | What it is |
|---|---|
LocalPlayer | Your player's state. Write it every frame; it is sent 20 times a second. |
RemotePlayers | Everyone else, by player id: info (username, user_id), away (reconnecting), visible, and current, the interpolated sample to show. |
NetEvents | Reliable messages. Push (channel, bytes) to outgoing; read incoming as (sender, channel, bytes). The relay forwards them to the room. |
NetStatus | The connection: state (Offline, Connecting, Connected, Reconnecting), your id, the host, the relay node, round-trip time, bytes and reconnects. |
NetSettings | Send rate (20 per second), keyframe interval, interpolation delay (0.1 s) and extrapolation cap (0.25 s). |
NetConfig | The session. Insert it yourself to connect somewhere else. |
On the web, the connection status is also published as JSON in window.__neo_net, which helps when testing with two browser windows.
Remote players and avatars#
RemotePlayers[id].info.user_id is the remote player's platform account, taken from their game token. A game can look up that player's avatar with AvatarService.GetAvatar; see How avatars work in games. The template doesn't apply remote players' avatars yet: other players show as the template mannequin.