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
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
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.
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:
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.
@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?
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.