Transports
In short
INetTransportis a star network: one host (peer 0) and up to 3 clients (peers 1-3) that only talk to the host. LOCAL is UDP on a port (join code7777, oraddress:porton a LAN) with its own resend-until-acked reliable channel. STEAM makes a friends-only Steam lobby (join code = lobby id) and connects over the Steam Datagram Relay. Steam code only compiles with theHOMERUNDERBY_STEAMdefine.
How it works
The interface (INetTransport): Host(), Join(code), Leave(), Send(peer, bytes, reliable),
Broadcast(bytes, reliable), Poll(); state IsActive, IsHost, IsConnecting, LocalPeerId, JoinCode,
Peers, LocalPlayerName, CanInvite / OpenInvite(); events PeerJoined, PeerLeft, Received, Log.
Everything happens on the main thread inside Poll(), which NetRuntime.Update calls once a frame.
Choosing one. NetRuntime.Use(Backend.Local | Backend.Steam) (the LOCAL / STEAM buttons in the lobby and NET TEST)
disposes the old transport, makes a new one and a new NetSession. It starts on Local. Without the define, asking for
Steam logs “Steam is not compiled in…” and stays on Local.
LocalTransport (UDP)
- Host binds UDP on the port (default 7777) on all addresses. Join code = the port.
- Join parses the code:
7777means127.0.0.1:7777;192.168.1.20:7777for another PC. It sendsConnectwith the transport protocolHRD-LOCAL-1every 0.5 s untilAccept(with its peer id) or 6 s pass. - The host refuses a different transport protocol (“different game version”) or a 4th client (“the game is full”). A repeated Connect from a known peer gets its Accept again.
- Reliable sends carry a sequence number, are resent every 0.2 s until acked, and are delivered in order (early ones are held, duplicates dropped). Unreliable sends are fire-and-forget.
- A heartbeat goes out after 1 s of silence. A peer silent for 10 s is dropped (“timed out”).
- Leave sends
Disconnectto every peer. - On Windows,
SIO_UDP_CONNRESETis turned off so one client quitting doesn’t stop the host from reading.
SteamTransport (relay)
SteamBootstrap.EnsureStartedinitialises the Steam client once with app id 480 and the relay network (callbacks run on the main thread fromPoll). Fails with “Steam is not available: … (is Steam running and signed in?)“.- Host creates a lobby for 4 (
MaxClients + 1), friends-only and joinable, with lobby datahrd_protocol = HRD-STEAM-1, then opens a relay socket (CreateRelaySocket<HostSocket>). Join code = the lobby id. - Join parses the code as a lobby id, joins the lobby, checks
hrd_protocol(“That lobby runs a different game version”), then connects over the relay to the lobby owner (ConnectRelay<HostLink>). - On connection the host gives the client the next id (1, 2, 3) and sends
[0xFF, id]first. A 4th client is closed atOnConnecting. - Reliable →
SendType.Reliable; unreliable →SendType.Unreliable | NoNagle. - INVITE FRIENDS (
OpenInvite) opens Steam’s invite overlay for the lobby (host only). - SteamOverlayJoin listens for
SteamFriends.OnGameLobbyJoinRequestedfrom game start, whatever backend is selected;NetRuntimepumps Steam callbacks while Local is active. See Lobby and Session. LocalPlayerNameis the Steam persona name.
The HOMERUNDERBY_STEAM define
SteamTransport.csis wrapped in#if HOMERUNDERBY_STEAM.NetRuntime.SteamCompiledtells the UI whether it is in.- Tools > Home Run Derby > Steam > Enable Steam checks that
Assets/Plugins/Steamworks/Facepunch.Steamworks.Win64.dllandsteam_api64.dllexist, writessteam_appid.txt(= 480) next to the project, and adds the define to the Standalone target. Disable Steam removes the define. - Tools > Home Run Derby > Build > Windows Player (zip) copies
steam_appid.txtnext to the built.exe(it warns if the file is missing). - On main the define is on (
ProjectSettings.asset:Standalone: HOMERUNDERBY_STEAM) and the Facepunch.Steamworks Win64 DLL, its XML docs andsteam_api64.dllare committed underAssets/Plugins/Steamworks/.
Numbers
| What | Value | Where to tune |
|---|---|---|
| Max clients | 3 (4 players) | LocalTransport.MaxClients, SteamTransport.MaxClients |
| Local default port | 7777 | LocalTransport.DefaultPort |
| Local connect retry / give up | 0.5 s / 6 s | ConnectRetrySeconds, ConnectTimeoutSeconds |
| Local heartbeat | 1 s | HeartbeatSeconds |
| Local peer timeout | 10 s | TimeoutSeconds |
| Local resend | 0.2 s | ResendSeconds |
| Local max message | 1200 bytes | MaxPacket |
| Local transport protocol | HRD-LOCAL-1 | LocalTransport.Protocol |
| Steam lobby protocol | HRD-STEAM-1 (lobby key hrd_protocol) | SteamTransport.Protocol |
| Steam app id | 480 | SteamBootstrap.AppId, SteamSetup.TestAppId, steam_appid.txt |
| Steam library | Facepunch.Steamworks 2.5.2 (per the plan) | Assets/Plugins/Steamworks/ |
In the code
| File | What it does |
|---|---|
Assets/_Project/Scripts/Net/INetTransport.cs | The interface |
Assets/_Project/Scripts/Net/LocalTransport.cs | UDP transport, reliable channel, heartbeats |
Assets/_Project/Scripts/Net/SteamTransport.cs | SteamTransport (HostSocket, HostLink), SteamOverlayJoin, SteamBootstrap |
Assets/_Project/Scripts/Net/NetRuntime.cs | Use(backend), Update polling, SteamCompiled |
Assets/_Project/Editor/SteamSetup.cs | Enable / Disable Steam menu items |
Assets/_Project/Editor/NetSelfTest.cs | Tools > Home Run Derby > Net > Run Local Transport Self-Test: host + two clients, reliable round trips, in-order burst, unreliable, clean leave |
steam_appid.txt | 480 |
Gotchas
Always call the base handlers in SteamTransport
HostSocketandHostLinkoverride Facepunch’sSocketManager/ConnectionManagercallbacks. Each override must callbasefirst:base.OnConnectedadds the connection to the poll group, and without it the host never hears a word from that client. That was the first Steam test’s bug, fixed in PR #27 (fix/steam-host-receive).
- One Steam account can be signed in once per machine, so two instances on one PC cannot both use Steam. Use LOCAL.
- There are three version strings:
HRD-LOCAL-1andHRD-STEAM-1at the transport level, andNetSession.ProtocolplusApplication.versionat the session level. See Protocol Versions. SteamSetup’s class comment says Facepunch.Steamworks “is not committed”. It is committed on main; the comment is stale.- Only the Win64 Steam pieces are in the repo; the game targets Windows.
- The Local port must be free: “Could not open UDP port … (is another instance already hosting on it?)“.
Related
- Lobby and Session: the session on top of a transport
- Net Messages: what travels over it
- Steam Test Guide: testing STEAM with two people
- Build and Release:
steam_appid.txtand the build