Sessions
Sessions
A higher level layer over lobbies: host and travel in one node, with standard metadata.
The lobby pages give you the raw pieces. The session layer stacks a common arrangement of them into single nodes, so you do not have to design your own metadata keys or remember the order of the host steps.
A session is a lobby, with agreed keys on it. Everything on the lobby subsystem still works underneath.
Use sessions if you want a working host and join flow quickly. Use lobbies directly if you want full control over the metadata.
What you need before hosting
Three things, and getting any of them wrong produces a failure that looks like something else:
| Requirement | Why | What goes wrong without it |
|---|---|---|
| A map to travel to, by asset name | The host travels there and listens for connections | Hosting reports success and nothing happens |
| Steam reporting Available: yes | Everything here is Steam matchmaking | Every node fails immediately |
| Two distinct Steam identities to test with | Two windows on one account are the same player | Joins appear to work and nothing is really tested |
The third is the one people lose time to. See Testing with two players.
Hosting
Host Session And Travel does five things in the right order:
- Creates the lobby.
- Publishes your session settings as lobby data.
- Sets Rich Presence, so friends get a Join Game button.
- Travels to the map as a listen server.
- Publishes the connect string that travel produced, so joiners can reach it.
Missing step 3 is why invites often do nothing. Missing step 5 is why players sit together in a lobby while the host plays alone.
The last two cannot be swapped. The listen server does not exist until the map has loaded and a port is bound, so there is nothing to publish before travelling. SteamForge keeps trying after travel until the server is genuinely up, which is why the node's On Success fires before the session is joinable.
| Input | Meaning |
|---|---|
| Settings | The session settings struct, below |
| Travel | Untick to create the session and stay put, for a pre match lobby |
The two ways to host
Which one you want depends on whether players gather first.
| Travel | What you get | Use it when |
|---|---|---|
| Ticked | The host goes straight into the match. Anyone who joins later follows immediately. | Drop in games, or a Play Now button |
| Unticked | A pre match lobby. Everyone gathers, nobody travels. | A ready up screen, team selection, map voting |
With Travel unticked, call Start Match when the match begins. It travels the session you already have.
What the joiners do
Nothing, in most cases. This is worth stating plainly because it is the part people write code for that they do not need.
- Joining a session the host has already started: Join Session reads the published address and travels there. Done.
- Joining a session the host has not started yet: the player stays in the lobby. When the host starts, SteamForge sees the address appear and travels them automatically.
Both paths are covered by one Join Session call with Travel ticked. Untick it if you want to handle travel yourself, and the automatic follow is disabled with it.
Session settings
| Field | Meaning |
|---|---|
| Session Name | Shown in the browser |
| Map Name | Where to travel. Required when Travel is on. |
| Game Mode | Free text, yours to interpret |
| Max Players | Including the host |
| Private | Friends only rather than publicly listed |
| Password | Optional. See passwords. |
| Build Id | Optional override for this session. Leave empty to use the project's. |
| Extra Data | Any other keys you want published and searchable |
Keeping incompatible builds apart
Two players on different builds can join each other and desync in ways that look like bugs in your game. Version gating stops that at the door.
It is off until you turn it on. Set Session Build Id in Project Settings > Plugins > SteamForge and three things start working at once:
| Where | What happens |
|---|---|
| Hosting | The value is published with the session automatically |
| Joining | A mismatch is refused with Version Mismatch before the player is in far enough to desync |
| Searching | Results carry Version Compatible, and Find Sessions can filter on it |
An empty value on either side means opting out, so a project that never sets one is unaffected.
Read the local value back with Get Local Build Id if you want to show it on a screen.
Finding sessions
Find Sessions returns results with their metadata already read:
| Field | Meaning |
|---|---|
| Session Name, Map Name, Game Mode | As the host published them |
| Current Players, Max Players | Occupancy |
| Host Steam Id | Who is hosting |
| Password Protected | Whether a password is needed |
| Version Compatible | Whether the host's Build Id matches yours |
Joining
Join Session takes a session, an optional password, and whether to travel. It reports a full diagnosis rather than a bare true or false. See Join diagnostics.
Managing a live session
On the SteamForge Sessions subsystem:
| Node | What it does |
|---|---|
| Is In Session | Hosting or joined |
| Is Session Host | The local player is the host |
| Get Session Settings | What the session was created with |
| Update Session Settings | Change them. Host only. |
| Start Match | Take this session into its map, bringing its members with you. Host only. |
| Set Session Joinable | Stop accepting new players without ending the session |
| Publish Connect String | Republish where the host is listening. Host only. |
| Get Session Connect String | The URL joiners travel to, or empty while the host has not started |
| Get Session Diagnostics | Every fact about the current session, as text you can put on screen |
| Destroy Session | Leave or end it |
All of these survive changing level, because the subsystem outlives the world. Is In Session still answers correctly once you are on the match map.
You only need Publish Connect String by hand if you travel some way other than Start Match: your own ServerTravel, or a map change between rounds. Both give the listen server a new address, and joiners cannot find you at the old one.
How joining actually works
Worth knowing, because it is one value and not a negotiation.
The host resolves the URL joiners should travel to and publishes it as session data. It is the only machine that can: it knows its own address, its own Steam identity, and which net driver this build uses. Joiners travel to that string verbatim.
| Direct IP | 192.168.1.33:7777 |
| Steam relay | steam.76561198012345678:7777 |
Read it on any machine with Get Session Connect String. Empty means the host has not started.
On OnlineSubsystem
Sessions publish as ordinary Steam lobby metadata, so anything that reads Steam lobbies can see a SteamForge session, including code using OnlineSubsystemSteam.
They do not route through the engine's IOnlineSession interface. Doing that would make the plugin depend on the OnlineSubsystem plugin, and working without it is the property SteamForge is built around. Interop happens at the data level, which is where Steam actually defines it.