OnlineSubsystemEOS の動作確認: 認証の確認

前回 EOS_Platform_Tick が呼び出されている箇所を確認したので、SDK の Sample で確認したように Callback が受け取れることが分かりました。
続いて認証について確認します。

EOS_Auth_Login の呼び出し箇所

SDK の Sample で確認した際は EOS_Auth_Login を利用していたので、今回もそこを起点に確認します。

FUserManagerEOS::LoginFUserManagerEOS::LoginViaExternalAuth の二箇所で使われていますが、今回は前者のみ確認します。

bool FUserManagerEOS::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials)
{
    LocalUserNumToLastLoginCredentials.Emplace(LocalUserNum, MakeShared<FOnlineAccountCredentials>(AccountCredentials));

    FEOSSettings Settings = UEOSSettings::GetSettings();

    // 略

    EOS_Auth_LoginOptions LoginOptions = { };
    LoginOptions.ApiVersion = EOS_AUTH_LOGIN_API_LATEST;
    LoginOptions.ScopeFlags = EOS_EAuthScopeFlags::EOS_AS_BasicProfile | EOS_EAuthScopeFlags::EOS_AS_FriendsList | EOS_EAuthScopeFlags::EOS_AS_Presence;

    FPlatformEOSHelpersPtr EOSHelpers = EOSSubsystem->GetEOSHelpers();

    FAuthCredentials Credentials;
    LoginOptions.Credentials = &Credentials;
    EOSHelpers->PlatformAuthCredentials(Credentials);

    if (AccountCredentials.Type == TEXT("exchangecode"))
    {
        // This is how the Epic launcher will pass credentials to you
        FCStringAnsi::Strncpy(Credentials.TokenAnsi, TCHAR_TO_UTF8(*AccountCredentials.Token), EOS_MAX_TOKEN_SIZE);
        Credentials.Type = EOS_ELoginCredentialType::EOS_LCT_ExchangeCode;
    }
    else if (AccountCredentials.Type == TEXT("developer"))
    {
        // This is auth via the EOS auth tool
        Credentials.Type = EOS_ELoginCredentialType::EOS_LCT_Developer;
        FCStringAnsi::Strncpy(Credentials.IdAnsi, TCHAR_TO_UTF8(*AccountCredentials.Id), EOS_OSS_STRING_BUFFER_LENGTH);
        FCStringAnsi::Strncpy(Credentials.TokenAnsi, TCHAR_TO_UTF8(*AccountCredentials.Token), EOS_MAX_TOKEN_SIZE);
    }
    else if (AccountCredentials.Type == TEXT("accountportal"))
    {
        // This is auth via the EOS Account Portal
        Credentials.Type = EOS_ELoginCredentialType::EOS_LCT_AccountPortal;
    }
    else
    {
        UE_LOG_ONLINE(Warning, TEXT("Unable to Login() user (%d) due to missing auth parameters"), LocalUserNum);
        TriggerOnLoginCompleteDelegates(LocalUserNum, false, *FUniqueNetIdEOS::EmptyId(), FString(TEXT("Missing auth parameters")));
        return false;
    }

    FLoginCallback* CallbackObj = new FLoginCallback();
    CallbackObj->CallbackLambda = [this, LocalUserNum](const EOS_Auth_LoginCallbackInfo* Data)
    {
        if (Data->ResultCode == EOS_EResult::EOS_Success)
        {
            // Continue the login process by getting the product user id for EAS only
            ConnectLoginEAS(LocalUserNum, Data->LocalUserId);
        }
        else
        {
            FString ErrorString = FString::Printf(TEXT("Login(%d) failed with EOS result code (%s)"), LocalUserNum, ANSI_TO_TCHAR(EOS_EResult_ToString(Data->ResultCode)));
            UE_LOG_ONLINE(Warning, TEXT("%s"), *ErrorString);
            TriggerOnLoginCompleteDelegates(LocalUserNum, false, *FUniqueNetIdEOS::EmptyId(), ErrorString);
        }
    };
    // Perform the auth call
    EOS_Auth_Login(EOSSubsystem->AuthHandle, &LoginOptions, (void*)CallbackObj, CallbackObj->GetCallbackPtr());
    return true;
}

まず EOS_Auth_LoginOptionsApiVersionScopeFlagsSDK の Sample と同じものが指定されています。

続いて Credentials ですが、EOS_Auth_Credentials が型になるはずですが、ここでは FAuthCredentials となっています。ただ、以下のように定義されているため同じです。

struct FAuthCredentials :
    public EOS_Auth_Credentials

    FAuthCredentials() :
        EOS_Auth_Credentials()
    {
        ApiVersion = EOS_AUTH_CREDENTIALS_API_LATEST;
        Id = IdAnsi; // 空
        Token = TokenAnsi; // 空
    }

その後で EOSHelpers->PlatformAuthCredentials(Credentials); が呼び出されていますが、実装が空なので結局は SDK の Sample と同じく ApiVersion のみ指定されたと考えてよさそうです。

続いて Callback ですが、成功時には SDK の Sample と同様に EOS_Connect_Login へと続けています。

よって、だいたいの流れは同じと考えて良さそうです。また、この辺のコードは FUserManagerEOS にまとまっているようです。

FUserManagerEOS は以下のように実装しているインターフェースが多いです。

class FUserManagerEOS
    : public IOnlineIdentity
    , public IOnlineExternalUI
    , public IOnlineFriends
    , public IOnlinePresence
    , public IOnlineUser

FUserManager を使う方法

前回見た FOnlineSubsystemEOS::Init 内で初期化されており FOnlineSubsystemEOS から呼び出すことができます。

また、上述したように実装しているインターフェースが多いので、 FOnlineSubsystemEOS の多くの Get メソッドから返される実態も UserManager になっています。

IOnlineFriendsPtr FOnlineSubsystemEOS::GetFriendsInterface() const
{
    return UserManager;
}

IOnlineExternalUIPtr FOnlineSubsystemEOS::GetExternalUIInterface() const
{
    return UserManager;
}

IOnlineIdentityPtr FOnlineSubsystemEOS::GetIdentityInterface() const
{
    return UserManager;
}

IOnlineUserPtr FOnlineSubsystemEOS::GetUserInterface() const
{
    return UserManager;
}

IOnlinePresencePtr FOnlineSubsystemEOS::GetPresenceInterface() const
{
    return UserManager;
}

ここまで見てきたように FOnlineSubsystemEOS は OnlineSubsystemEOS を使う際の公開部分なので、直接 OnlineSubsystem として取得することができます。

[UE4] 複数のOnlineSubsystemを併用する #UE4 - Qiita

今回はデフォルトを EOS にしてあるので、

[OnlineSubsystem]
DefaultPlatformService=EOS

以下で取得することができます。

IOnlineSubsystem::Get();

FUserManagerEOS::Login が他に呼び出される箇所

UOnlineEngineInterfaceImpl::LoginPIEInstance で呼び出されることが確認できました。

以下から Credential 情報を取得し PIE 起動時に渡しているようです。後日ちゃんと試してみようと思います。

まとめ

今回は、認証の簡単な流れを SDK の Sample と比較しつつ眺めました。当たり前かもしれませんが、SDK で説明されていることと同じように実装されているように見えました。

いくつかマクロでわからない部分があったりしたので、そこは別途拾ってみようと思います。