Dedicated server with Steam is a joke

I can confirm that creating and connecting to dedicated servers with Steam works in 4.18.1. Took me about a day to get working (Note: this was only tested with Development builds)

However, the steps I took to get this to work are non-trivial. A quick summary:

  • First get your normal Steam integration with lobbies working
  • Copy OnlineSubsystemSteam to your own Plugins directory and modify it in several places to be recognized as a new OnlineSubsystem.
    follow A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums
  • Replace any usage of STEAM_SUBSYSTEM with your own macro FName
  • Assign this plugin as your DefaultPlatformService in DefaultEngine.ini
  • Set both STEAMPRODUCTNAME and STEAMGAMEDIR to what you set in Steamworks for your project, or “Spacewar” for testing.
  • There is an issue with GameTags overflowing, so change OnlineSessionAsyncServerSteam.cpp:133 in your plugin to KeyValuePairs.Add(STEAMKEY_OWNINGUSERNAME, “Bob”);// Session->OwningUserName);
  • Override the GameSession::RegisterServer() as described in the first page of this thread (make sure to set bUsesPresence=false).
  • Forward port 27015 to your machine.

At this point it should show up in the Steam Server Browser.

To then have clients find the sessions:

  • Copy and rename FindSessionsCallbackProxy to make your own version in your project
  • The above also requires your own copy of the FOnlineSubsystemBPCallHelper due to header scoping
  • In ::Activate() change the presence setting to SearchObject->QuerySettings.Set(SEARCH_PRESENCE, false, EOnlineComparisonOp::Equals);

This will give you a new FindSessions blueprint which searches for Servers instead of lobbies.

Finally, when creating a packaged build, make sure to include a steam_appid.txt next to your .exe in /Binaries/Win64/

Some notes:

  • it is likely possible to create a minimalistic plugin that doesn’t re-implement everything, but only the required pieces. I have not tried yet.
  • This is hardcoding the server name (one of the two, the one that doesn’t show in the server browser, but those in the BlueprintSessionResult)
  • This solution is… hacky at best. However, it does not require any engine modifications.