Passing Options Trhough Join Session Node?

Hi,

How can I pass options to the server when connecting to it using the Join Session node? it only has Player Controller and Session inputs.

Or is there another way of connecting?

Join Session | Unreal Engine Documentation

Thanks :wink:

What exactly are you trying to do? I ask this because you can use the player controller if you want to send some data after joining the session.

@BladeMaster I’d like to ask the player to input a password which would be sent to the server as an option, and compared to the server’s password in the PreLogin event. The PreLogin event will then either allow them to fully connect or kick them.

i wonder if it would be easier to let them, join, then ask for a password. Like a login server.

Then you can pass code to the server, and if its bad, kick them from there.

@Lammosan Yeah, that is an option but it’s not the perfect option because if you let them join, they’ll have a player controller assigned, take up space on the server, appear in the player list, and the other players will be notified that they joined etc. Plus, if they’re a hacker they might be able to run some kind of script on the server in that brief moment.

I think that the best thing to do is to check the password in the PreLogin event. I got the ban list to work there so it would be a shame if the password didn’t.

Curious. Excellent point, but, if theyre allowed to send a password, is it also not possible for them to run a script from that point?

Its just that you might be asking for too much. I know a login server requires you to log in to the login server, before you actually load into the game. Im betting thats your best bet.

Just force the client into a login place, before it loads any of the identifying information to the rest of the server. Create a bridge to your game, essentially.

Its programming, we can be lazy if we want, but we always pay for it sooner or later.

Do you know if there’s a way to overwrite the Join Session / Join Session Callback Proxy nodes, or at least see how they work and if it’s even possible to pass a parameter through them?

I know that passing a parameter is easy with the Open Level node.

Hey, did you have a look at the Beacon system? I have not used it myself but maybe that would work?

Yes you can. All you have to do is override GetResolvedConnectString in your corresponding OSS code, and just attach the password to the ConnectInfo string.

Another option would be to have some sort of object that carries data between levels, for example a LocalPlayer subsystem, and inside PreLogin you pull the data from your subsystem and check against the database if it’s correct. More info on how to persist data can be found here.

Thanks for the reply.

I’m using Steam Advanced Sessions and the Join Session Node to join a session.

Node

Where is GetResolvedConnectString located? Is it in the Game Instance? When is it called, after the Join Session function? Does the Join Session function pass information to it? How do I pass my password into it? And how do I get the password out of it in PreLogin?

I know how to override events but I’m still new to C++ and programming in UE4. Would you be so kind as to create a small example that I and others could use and build upon?

It’s part of the OSS you’re implementing. At this point I would suggest you leave everything, and learn C++. Then when you’re confident with C++, you have to pick up an OSS to implement. By default, you implement the Null Subsystem. If you want to release it on Steam, then you implement Steam OSS. If you want to release on EGS and you want cross play support, then you implement EOS. Once you figured all the previous, go back to my previous answer and you should have a clear vision of what you should do. Also all your questions will be answered if you look into the source code of that function and in general. Relying on UE web docs (and YT tutorials) is a bad habit you should avoid.

Here is what you can do to validade a password before joining a session:

First of all, while creating an advanced session, make an extra setting named “password” and set a password (like 123456).

Then on the client side, before joining the session, try to validade the password from the session result like this:

If the password input is equal to the server password setting, then the client will join session.

If you want to change the password later, you can update session like this:

2 Likes

Thanks for the detailed answer!

The problem with this approach is that the password is sent to the client. So, all the user has to do is find out which password was sent and gain access to the server. That’s why I’d like the server to decide whether to accept/decline the connection. That way the password is never sent to the client.

okay, i think i found a decent solution for this. i’m not great at networking nor c++, so there’s probably a better way, but if you want players to optionally lock their servers with a password, here’s how i did it:

don’t use extra settings in the session nodes for passwords. the check to see if the password is correct will be executed on the client, and that can be bypassed - especially if the server password is in plaintext. you’ll want to check if it’s correct on the server, and before the player officially joins.

create two new c++ classes. one a child of the LocalPlayer class (which is persistent throughout server travels), and the other a child of the GameModeBase class. name 'em whatever you like.

go to Project Settings->General Settings->Default Classes. set the Local Player Class to the localplayer class you just created. then, reparent the gamemode to your gamemodebase class.

okay, now open up your localplayer class. we’re gonna use GetGameLoginOptions to pass an additional string to the login options. this string will be an editable variable called ServerPassword.

UCLASS(BlueprintType)
class DEEPTERROR_API UDeepTerrorLocalPlayer : public ULocalPlayer
{
	GENERATED_BODY()

	virtual FString GetGameLoginOptions() const { return TEXT("Password=" + ServerPassword); }

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FString ServerPassword;
}

get the localplayer, cast it to your custom localplayer, and set the serverpassword to whatever your password input is before you create a session and join a session. you might want to generate a hash from the string here using the low entry library.

alright, cool. now as a joining client your password is injected into the login options, and as a host you have access to your server password through the localplayer. now, we want to check whether they match.

so, we’re gonna override the prelogin function on your new gamemode. this function calls on the server when a player attempts to join your game. the Options string in the function will contain the password we passed through earlier as the client.

ADeepTerrorGameMode.h

virtual void PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage) override;
};

if the ErrorMessage string is not empty, the joining player is rejected from joining the server. so, if the parsed password is the same as the server password, we leave it blank - if not, we set it to a string.

#include "Kismet/GameplayStatics.h" for the handy ParseOption function (so we can find the value for the key “Password”), and #include "ProjectName/YourCustomLocalPlayer.h" so you can cast the localplayer to your own custom localplayer.

ADeepTerrorGameMode.cpp

void ADeepTerrorGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
{
	if (GetWorld()->GetFirstLocalPlayerFromController()) {
		FString ParsedPassword = UGameplayStatics::ParseOption(Options, TEXT("Password"));
		FString ServerPassword = Cast<UDeepTerrorLocalPlayer>(GetWorld()->GetFirstLocalPlayerFromController())->ServerPassword;
		
		if (ParsedPassword == ServerPassword) {
			ErrorMessage = "";
		}
		else {
			ErrorMessage = "wrongpassword";
		}
	}
	else {
		ErrorMessage = "";
	}

	FGameModeEvents::GameModePreLoginEvent.Broadcast(this, UniqueId, ErrorMessage);
}

and, that should be all! now your password checking is done the server, and everything should be secure. again, i’m no expert, i’m just developing a relatively simple 4-player listen server co-op game, so… ya know… do your own research.

thank you to @wizardcell for the Unreal Engine Persistent Data Compendium of which i understood at most 20 percent.

5 Likes

@ervin Thanks, I’ll try that out and let you know if it works.

Have you tried if you can connect to a password-protected server through the Steam server browser?

You wouldn’t happen to know how to get the Steam server browser to display the lock icon for password-protected servers?

steamicon

1 Like

i’m honestly not too sure. i’m going to look into this and see how the server browser works with advanced steam sessions and i’ll get back to you later.

sorry, i couldn’t figure the steam server browser out lol. i can only really give you some pointers.

look into: ISteamGameServer Interface (Steamworks Documentation) and Implementing the Steam SDK with Unreal Engine 4 - Absolly.me

you’ll have to add

"Steamworks", "OnlineSubsystem", "OnlineSubsystemSteam", "OnlineSubsystemUtils"

to PublicDependencyModuleNames in the {projectname}.Build.cs file, which should be in the “{projectroot}/Source/{projectname}/” folder.

then, you can include parts of the steamapi. #include "steam/steam_gameserver.h" will give you access to the steam game servers API.

from there, you shooooouuuld be able to call SteamGameServer()->SetPasswordProtected(true); to display the lock icon for password-protected servers. you might also have to call “SteamGameServer()->LogOnAnonymous()” to update the game server master list… probably. this is all conjecture, you’d probably be better off asking someone more knowledgable here.

as for connecting to a password-protected server, you’ll have to bind to a callback for joining from a server list. you’ll want to use GameServerChangeRequested_t which returns the server address and the inputted password. look into OnlineSubsystemSteam/Source/Private/OnlineAsyncTaskManagerSteam.h to see how you can bind to GameServerChangeRequested_t, that’s where the steam callbacks are registered to delegates for OnlineSubsystemSteam. then you can presumably join the session with that IP and set the server password in localplayer like before.

yeah, it’s a little complicated unfortunately. if you’re struggling i suggest grabbing the steamcore plugin from the marketplace. it’s expensive but it exposes a lot of steam interfaces for ya.

EDIT:
look into OnlineSessionAsyncServerSteam.cpp. move the OnlineSubsystemSteam plugin into your project plugin folder so you can edit it. whilst you’re here, change some of the defines here to get your game to properly show up on steam’s master server list. if you have your game on steamworks, you can change the game master server information in Application->Dedicated Servers and match UE_PROJECT_STEAMPRODUCTNAME and UE_PROJECT_STEAMGAMEDIR to that.

from there, in void FOnlineAsyncTaskSteamCreateServer::Tick(), under SteamGameServerPtr->SetDedicatedServer(bWantsDedicated); you can use SteamGameServerPtr->SetPasswordProtected(true); to show the lock icon.

obviously, you’ll need to come up with a way to only show the lock icon if the server is password protected. you could maybe edit FOnlineSessionSettings to include a bPasswordProtected boolean but that might be a little too much work and you probably shouldn’t mess with OnlineSubsystem too much (i don’t really know why FOnlineSessionSettings doesn’t just have a bPasswordProtected boolean, but oh well)

if you’re not planning to use anti-cheat, you cooould technically just comment out whatever makes steam display the VAC icon (m_bSecure?) and plug that into set password protected like so SteamGameServerPtr->SetPasswordProtected(Session->SessionSettings.bAntiCheatProtected); so all you have to do is tick bAntiCheatProtected on the CreateAdvancedSession node, but that might be a little too hacky lol.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.