PlayEveryWare / eos_plugin_for_unity

Repository for PlayEveryWare's EOS Plugin for Unity, bringing the functionality of Epic Online Services to the Unity Game Engine.
https://eospluginforunity.playeveryware.com
288 stars 56 forks source link

What is the correct way to login to Epic Games Store? #262

Closed raptorclawgames closed 1 year ago

raptorclawgames commented 1 year ago

Hello,

I don't know how much about Epic's API and documentation can be exposed here, so If you excuse me I will be vague on the description for the moment.

We are trying to publish on Epic Games Store on PC for the first time. I have been trying to pass the verification for days. They claim that the overlay is not showing and for that reason they can't access achievements data. I have asked for support and the only thing I know so far is that when trying to execute CreateConnectUserWithContinuanceToken the ContinuanceToken is null.

On our own machines the build is acting just fine. The game is connecting to the store and the overlay is displayed. We can check the achievements there, and unlock achievements from the game. Those unlocked achievements are appearing in the Epic dashboard analytics, even in their Live deployment.

So the question is simple, "What is the correct script to login to Epic Games Store?". There must be a really simple way to do it due to that their store is the go-to way to access their services, but I've missed an answer to that question. For now I am guessing that we must assume the persistent login will succeed, and if not try another ways. But I have no clue why is failing in stage and not in dev.

This is the code we are using at the start of the application. We may be missing something obvious, but we are stuck with this issue.

At this point we are having to delay the launch of the game due to this issue, so the situation is a bit tense right now.

Thank you!

void Start()
    {

        EOSManager.Instance.StartPersistentLogin((Epic.OnlineServices.Auth.LoginCallbackInfo callbackInfo) =>
        {
            // In this state, it means one needs to login in again with the previous login type, or a new one, as the
            // tokens are invalid
            if (callbackInfo.ResultCode != Epic.OnlineServices.Result.Success)
            {
                Debug.Log("Failed to login with Persistent token [" + callbackInfo.ResultCode + "]");

                // ask user if they want to connect; sample assumes they do
                EOSManager.Instance.CreateConnectUserWithContinuanceToken(callbackInfo.ContinuanceToken, (Epic.OnlineServices.Connect.CreateUserCallbackInfo createUserCallbackInfo) =>
                {
                    print("Creating new connect user");
                    EOSManager.Instance.StartConnectLoginWithEpicAccount(callbackInfo.LocalUserId, (Epic.OnlineServices.Connect.LoginCallbackInfo retryConnectLoginCallbackInfo) =>
                    {
                    });
                });

            }
            else
            {
                Debug.Log("EOS LOGGED with Persistent token [" + callbackInfo.ResultCode + "]");

                StartLoginWithLoginTypeAndTokenCallback(callbackInfo);

                //init achievements
                achievementManager = EOSManager.Instance.GetOrCreateManager<EOSAchievementManager>();
                achievementManager.GetAchievementDefinitionCount();
                achievementManager.EnumerateCachedAchievementDefinitions();
                var userId = EOSManager.Instance.GetProductUserId();
                if (userId.IsValid())
                    achievementManager.EnumerateCachedPlayerAchievement(userId);

                achievementManager.AddNotifyAchievementDataUpdated(OnAchievementDataUpdated);

                IncrementLoginStat();
            }
        });
    }
andrew-hirata-playeveryware commented 1 year ago

That looks more or less correct: For launching from the Epic Game's Launcher, you'll need to use EOSManager.instance.GetCommandLineArgsFromEpicLauncher() to get the tokens to login from the launcher, i.e. to use the same login credentials that the user is logged into the EGS with. How are you doing the initial login: account portal?

raptorclawgames commented 1 year ago

Hi Andrew, thanks for your quick response.

What you have seen in the code is all I am doing, if any additional steps are needed, I am missing them.

Maybe the cause of me not being able of replicate the problem is that I have some kind of authentication token cached on my PC from previous versions, and for that reason the persistent login is not failing me, but other people.

At this point I am thinking on adding this step:

EOSManager.EOSSingleton.EpicLauncherArgs argsEpic = EOSManager.Instance.GetCommandLineArgsFromEpicLauncher();

EOSManager.Instance.StartLoginWithLoginTypeAndToken(LoginCredentialType.AccountPortal,
                                                                argsEpic.epicUsername,
                                                                argsEpic.authPassword,
                                                                StartLoginWithLoginTypeAndTokenCallback);

And sequence it as:

If Persistent login fails: 
-> GetCommandLineArgsFromEpicLauncher() // (as seen above)
-> StartLoginWithLoginTypeAndToken() // (as seen above)

If StartLoginWithLoginTypeAndToken succeeds:
-> StartLoginWithLoginTypeAndTokenCallback() //copy pasted from the plugin's login example
If StartLoginWithLoginTypeAndToken fails:
->CreateConnectUserWithContinuanceToken();

What do you think?

andrew-hirata-playeveryware commented 1 year ago

Yup! that sound like the correct course of action!

raptorclawgames commented 1 year ago

Ok, I will try to upload a compilation using this approach.

On another PC I noticed a difference in behaviour. With the old version, the game simply continues to run regardless of login status with no overlay. In the new version, it opens a browser tab asking to link the game to an Epic account. When that step fails, it is no longer able to login (never open that tab again, like something wrong gets cached) and behaves just like the old version.

I don't know if it will be enough yet, but it seems like progress.

I'll know tomorrow.

raptorclawgames commented 1 year ago

As reference, this is what I got so far.

EOSLogin.cs.txt

raptorclawgames commented 1 year ago

Still locked, can't pass the Stage review.

Also, I have seen their error logs, and I've been able to replicate their same error on one of my machines. It only happens on a Windows user session that never logged into Epic Store. Looks like that Persistent and Account Portal logins fail, and the callback to Create User returns a callbackInfo.LocalUserId Null.

2023-04-27T11:50:53.9500917+02:00 LogEOSOverlay(Error): Unable to GetDisplaySettings after successful LoadURL.
2023-04-27T11:50:53.9500917+02:00 LogEOSAuth(Error): BeginDesktopCrossplayLogin: Failed to receive exchange code from desktop crossplay: EOS_Canceled
2023-04-27T11:50:53.9500917+02:00 LogEOSAuth(Error): BeginDesktopCrossplayLogin: Desktop crossplay is required for login
2023-04-27T11:50:53.9541175+02:00 LogEOSConnect(Error): Invalid parameter EOS_Connect_CreateUserOptions.ContinuanceToken reason: property must not be null
Creating new connect user
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)
<>c__DisplayClass2_0:<CreateAndConnectWithContinuanceToken>b__0(CreateUserCallbackInfo)
PlayEveryWare.EpicOnlineServices.<>c__DisplayClass47_0:<CreateConnectUserWithContinuanceToken>b__0(CreateUserCallbackInfo&)
Epic.OnlineServices.Bindings:EOS_Platform_Tick(IntPtr)
PlayEveryWare.EpicOnlineServices.EOSManager:Update()

Uploading Crash Report
InvalidOperationException: Nullable object must have a value.
  at System.Nullable`1[T].get_Value () [0x00000] in <00000000000000000000000000000000>:0 
  at PlayEveryWare.EpicOnlineServices.EOSManager+EOSSingleton.StartConnectLoginWithEpicAccount (Epic.OnlineServices.EpicAccountId epicAccountId, PlayEveryWare.EpicOnlineServices.EOSManager+OnConnectLoginCallback onConnectLoginCallback) [0x00000] in <00000000000000000000000000000000>:0 
  at PlayEveryWare.EpicOnlineServices.EOSManager+EOSSingleton+<>c__DisplayClass47_0.<CreateConnectUserWithContinuanceToken>b__0 (Epic.OnlineServices.Connect.CreateUserCallbackInfo& createUserCallbackInfo) [0x00000] in <00000000000000000000000000000000>:0 
  at Epic.OnlineServices.Bindings.EOS_Platform_Tick (System.IntPtr handle) [0x00000] in <00000000000000000000000000000000>:0 
  at PlayEveryWare.EpicOnlineServices.EOSManager.Update () [0x00000] in <00000000000000000000000000000000>:0 

2023-04-27T11:50:54.1741715+02:00 LogEOS(Warning): Error response received from backend. Response is not JSON. ServiceName=[EOSHAuth], OperationName=[LoginCancel], Url=[<Redacted>], HttpStatus=[404], CorrId=[f09a22f8-a5f5-472d-870f-cd6e02703af9]
2023-04-27T11:50:54.1741715+02:00 LogEOSAuth(Error): FAccountPortalBrowserManager::FAccountPortalBrowserStateData::Finish: [RequestDesktopCrossplayExchangeCode] Cancel failed: EOS_NotFound
2023-04-27T11:50:54.4754134+02:00 LogEOSAnalytics(Warning): EOS SDK Analytics disabled for route [1].
SKIPPED STEP
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:LogError(Object)
<WaitTimeOrSkip>d__3:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

I have discovered something very important. I must not log in immediately at Start(), I must wait a few seconds to do so and then the login dialog may appear. Otherwise it won't. Just by adding that wait the error above does not happen because the login dialog returns a successful authentication.

   IEnumerator Start()
    {
        yield return new WaitForSecondsRealtime(2f); 

        NewLogin();
    }
raptorclawgames commented 1 year ago

After working all day on solving the problem, here's an update:

Reason
Other
Comments
**EOS overlay is still not configured in your build**. If you are having trouble integrating this, I would highly recommend making a post in the EOS Help Forums. They are supported by our Dev Relations Team and will definitely be able to help you

This is so frustrating I am starting to seriously considering on giving up. This is extremely basic stuff, just logging in at the program's startup. I can not be that complicated.

This is my current script for now. EOSLogin.cs.txt

I will ask them if they even cleaned and revoked their permissions before testing the program, it is the only thing I can think of that can explain this behaviour.

raptorclawgames commented 1 year ago

This is the solution:

If you want to publish to the Epic Store on PC you don't have to worry about Persistent login, Account Portal login or anything like that. Just a call to ExchangeCode a few moments after starting the game.


IEnumerator Start()
{
    yield return new WaitForSecondsRealtime(2f); //you need to wait a while from app's startup, or will start to behave weirdly

    Login_ExchangeCode();
}

void Login_ExchangeCode()
{
    EOSManager.EOSSingleton.EpicLauncherArgs argsEpic = EOSManager.Instance.GetCommandLineArgsFromEpicLauncher();

    EOSManager.Instance.StartLoginWithLoginTypeAndToken(LoginCredentialType.ExchangeCode,
                                                                argsEpic.epicUserID,
                                                                argsEpic.authPassword,
                                                                (Epic.OnlineServices.Auth.LoginCallbackInfo callbackInfo) =>
                                                                {
                                                                    if (callbackInfo.ResultCode != Epic.OnlineServices.Result.Success)
                                                                        CreateAndConnectWithContinuanceToken(callbackInfo);
                                                                    else
                                                                    {
                                                                        HandleOnAuthSucceded(callbackInfo);
                                                                    }
                                                                }
                                                                );
}
andrew-hirata-playeveryware commented 1 year ago

I'm glad you were able to resolve this, and I'm sorry that was such a frustrating task.

We've been working on creating an FAQ section for our documentation, and I've created a task with a link to this git issue to so that we can hopefully help more users in the future when they run into this kind of issue.