How do I connect to a game using the online subsytem?

I’ve seen a couple of little blurbs about it, I’ve read the small bit of documentation, and I’ve even perused and tried to replicate how the shooter game works, but I still can’t figure out how to do something as simple as host a game and then join that game. This problem doesn’t seem to be a simple one, so try and break it down:

What I want to be able to do

-Host a networked lobby that other players can find and join. I’m trying to echo what the shooter game does, in that I want to press a button to host a lobby, and I want a player in another game to press a button to search for a game, to be able to find the hosted game, and to join that game (which will be the lobby)

-Let players select classes in the lobby, and then connect to the actual game session with the players being given the classes they selected in the lobby. Once the game ends, I want the players to then switch back to the lobby, be able to select classes again, have updated scores, and then be able to jump back into another game session to play again.

What I’ve been trying to do

-For now, I’ve just been trying to host a game and connect a game. I’ve used the shooter game code, minus all the UI that I don’t care about, and I’ve gotten as far as activating my create server code, and changing my game mode. I’m not sure if this has actually created a server, although it goes through the same process as the shooter game so I believe it should.

-I have created a way to connect to a server, and I have tried to use it, but it never finds a server game to connect to.

Code Samples of what I’ve done so far

Note: This code has been put into a player controller class that I’m using for what would be my menu game mode.
-Code for hosting game, similar to the HostFreeForAll code in the Shooter game’s ShooterMainMenu.

void AHitPlayerController_Menu::HostHit()
{
	//modify string to specify game time and level
	FString StartStr = FString::Printf(TEXT("/Game/HIT_Maps/Main_Level?game=Hit?listen%s"), TEXT(""));

	if (this->CreateGame(LOCTEXT("Hit", "Hit").ToString(), StartStr))
	{
		FSlateApplication::Get().SetFocusToGameViewport();
	}
}

-Code for finding and joining a game. Mostly a custom made function that makes several calls that would be found in the ShooterGameMode_Menu and ShooterGameSession.

//begin server search, or join if found
void AHitPlayerController_Menu::BeginServerSearch()
{
	//bLANMatchSearch = bLANMatch;
	UWorld* const World = GetWorld();
	AHitGame_Menu * Game = World->GetAuthGameMode<AHitGame_Menu>();
	if (Game)
	{
		AHitGameSession* session = Cast<AHitGameSession>(Game->GameSession);
		int searchResults, numSearchResults;

		//get the state of the results
		EOnlineAsyncTaskState::Type searchState = session->GetSearchResultStatus(searchResults, numSearchResults);

		//switch off
		switch(searchState)
		{
			//fall through, if failed or not started, attempt to find session
		case EOnlineAsyncTaskState::Failed :
		case EOnlineAsyncTaskState::NotStarted :
			Game->FindSessions(this, false);
			break;
			//if done, join first abailable server
		case EOnlineAsyncTaskState::Done :
			//check if tried to connect, prevents screwing up the system if you try to connect in time between connection and first attempt
			const TArray<FOnlineSessionSearchResult> & SearchResults = session->GetSearchResults();
			if (!bTriedConnect)
			{
				if (numSearchResults == 0)
				{
					GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Search Failed"));
					Game->FindSessions(this, false);
				}
				else
				{
					const FOnlineSessionSearchResult & Result = SearchResults[0];
					GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, Result.Session.OwningUserName);
					bTriedConnect = true;
					Game->JoinSession(this, 0);
				}
			}
			else
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Already tried to connect"));
			}
			break;
		}
	}

How I’ve tried to test this

I’ve opened 2 editors on my computer, and I’ve ran them both with my menu gamemode. Using a button corresponding to the HostHit function, I’ve hosted a game in one editor. This changes that gamemode to the gamemode I want (the game is in the same map, but I’m assuming it reloads the map).

In the other editor, I use button presses corresponding to the BeginServerSearch function. I know this begins the process, but whenever it finishes, it always prints out Search Failed, meaning it found 0 servers in its search results. So it didn’t find anything. I’ve also echoed what the shooter game has done in it’s Build.cs and it’s config files, to no avail.

There’s not really enough information here to completely diagnose the issue, but the important thing to check on the server is whether the IOnlineSession::CreateSession function is returning true (In ShooterGame this is called in AShooterGameSession::HostSession). Are there any messages in the log about session creation? Are you trying to create LAN or internet matches (is the bIsLANMatch bool in your session settings object true or false)?

Just to confirm, does ShooterGame multiplayer work for you by following the same steps (as much as possible)?

Try setting bIsLANMatch to true for your sessions. The Null online subsystem only supports LAN matches.

There is also a known bug where LAN matches aren’t advertised on the network until the session in started. Try calling StartSession after CreateSession.

The Create Session function is returning true, and I’m trying to create internet matches.

In the log, first of all then I start the game, it says NULL: Cannot create session “Game” session already exists/

When I then start hosting a server, it begins with the log:
LogGameMode: Process ServerTravel: /Game/Hit_Maps/Main_Level?game=Hit?listen

Then it does a bunch of stuff until it gets to this, which is in yellow

LogSockets: Failed to create socket SessionSocket [Unreal]

followed by

LogInit: WinSock: Socket queue 131072 / 131072

And some networking and game loading related stuff.

It does work in the shooter game following my same section, at least as far as finding the server. It can’t actually connect, but the actual search works. In my game I can’t even get that far.

I’ve tried changing bIsLanMatch to true, but so far there is no change, so I will try calling StartSession as recommended, and making sure that I am setting it correctly in all cases.

However, I would like to ideally set this up through Steam. I’ve downloaded the Steam SDK and went through the process of putting files in the right places, but I have not compiled the newest engine source, and I don’t know how to test the steam online subsytem (especially since I’ve had so much trouble with this.)

To switch to the Steam subsystem, you’ll need this entry in your game’s DefaultEngine.ini file:
[OnlineSubsystem]
DefaultPlatformService=Steam

And you’ll need to make sure it’s set as a dependency in your Build.cs file:
DynamicallyLoadedModuleNames.Add(“OnlineSubsystemSteam”);

You can look at ShooterGame for an example of this as well, especially the [OnlineSubsystemSteam] section of DefaultEngine.ini, which is where you can set up data such as your app id.

Do I have to have the latest source compiled with the steam sdk files in their folder in order for it to work?

As far as I know the Steam online subsystem works in 4.1. You will still need to copy the SDK files, though.