Epic Online Services サンプルのコードリーディング: EOS Connect インターフェースについて

前回 の最後で、以下の疑問が出ました。

  • EOS Connect インターフェースでのログインはどういうことか
  • EOS_EpicAccountIdEOS_ProductUserId はどのように違うのか

今回は P2PNAT のコードリーディングを少し寄り道して、上記について見ていきたいと思います。

Connect インターフェース | Epic Online Services ドキュメンテーション

Epic アカウント

Auth インターフェース | Epic Online Services ドキュメンテーション

Auth インターフェースでは、ローカル ユーザーが Epic アカウントを使用してログインすることができます。これにより、Friends インターフェース、Presence インターフェース、UserInfo インターフェース、Ecom インターフェースなどの Epic Account Services (EAS) が提供する各種機能にアクセスできます。Auth インターフェース は、EOS との Epic アカウント関連のインタラクションを処理し、ユーザーを認証してアクセス トークンを取得する機能を提供します。

Epic Online Service とは別に Epic Account Service があり、Epic アカウントはそこに属するユーザーのようです。

ID プロバイダを管理する | Epic Online Services ドキュメンテーション

Epic Online Services (EOS) は、Identity Provider (ID プロバイダ) (または「プラットフォーム」) と呼ばれる複数のオンライン ストアおよびゲーム サービスのプレイヤー アカウントをリンクすることができます。これにより、ユーザーは使用するさまざまなプラットフォーム間でデータを共有し、マッチメイキングなどのクロスプラットフォーム機能に参加できます。 EOS がサポートする ID プロバイダー:

上記ドキュメントにあるように、EOS は Identity Provider で、EOS のアカウントと、外部のサービスをリンクすることができます。その中に 「Epic Games」も含まれており、Epic Account Services がそこに該当すると考えられます。
ドキュメントにある通り、Epic Games だけは EOS での外部プロバイダ設定が不要であるため、私の設定画面ではなにも追加されていない状態です。

f:id:you1dan:20220120073520p:plain

よって、Epic アカウントは、Steam 等のアカウントと同じと考えれば良さそうです。

Connect インターフェース | Epic Online Services ドキュメンテーション

Connect インターフェース を使用すると、外部 ID プロバイダ が Epic Online Services (EOS) エコシステムを統合して使用することができます。
Connect インターフェース では、次のことを行うことができます。

・Epic Online Services (EOS) ゲーム サービスにアクセスできる。
クロスプラットフォーム サービス内で、共通の一意のユーザー識別子を生成する。
・外部 ID プロバイダのアカウントを Epic Games のサービスにリンクさせる。

プレイヤーは、1 つまたは複数の外部ユーザー アカウントを、自分の 製品ユーザー ID (一意のプレイヤー ID) と関連付けることができます。

ここで Connect インターフェースが出てきますが、上記のように Connect インターフェースを使用することを前提として「EOS ゲームサービスにアクセスできる」というところが一つポイントです。

つまり、今回読んでいたサンプルで、私は Epic アカウントでログインをしていましたが、それだけでは EOS のサービス(例えば NATP2P など)を利用することはできません。
一方で、「外部 ID プロバイダのアカウントを Epic Games のサービスにリンクさせる」に関しては、Epic アカウントであればそもそも Epic Games のサービスを受けられるので、ここに Epic アカウントの特殊性はあるように思います。

リンクとはなにか

「リンク」に関してですが、以下の 2 つのリンク機能が存在します。

  • EOS_Connect_LinkAccount | Epic Online Services ドキュメンテーション
    • Link a set of external auth credentials with an existing product user on the Epic Online Service.

  • EOS_Auth_LinkAccount | Epic Online Services ドキュメンテーション
    • Link external account by continuing previous login attempt with a continuance token. On Desktop and Mobile platforms, the user will be presented the Epic Account Portal to resolve their identity. On Console, the user will login to their Epic Account using an external device, e.g. a mobile device or a desktop PC, by browsing to the presented authentication URL and entering the device code presented by the game on the console. On success, the user will be logged in at the completion of this action. This will commit this external account to the Epic Account and cannot be undone in the SDK.

上記は EOS の Connect インターフェースと EAS (Epic Account Service) の Auth インターフェースにそれぞれ存在しています。

これらは全く異なる機能であり、それは引数となるオプションを見ても読み取れます。

つまり、Connect インターフェースがリンクするのは「製品ユーザー ID と外部 ID」、Auth インターフェースがリンクするのは、「(Epic 以外の) 外部 ID と Epic アカウント」ということになりそうです。

製品ユーザーID については、以下のスライドの説明がわかりやすいです。 https://image.slidesharecdn.com/whatyoucandowithepiconlineservice202007-200720062123/95/epic-online-services-20-638.jpg?cb=1595241698 Epic Online Services でできること

Connect インターフェースと Auth インターフェースについて

自分でも理解できているか怪しくなってきたのでもう少し調べます。

Epic アカウント サービス(EAS)によるプレイヤー認証 - Epic Online Services

上記からの長めの引用になりますが。

よくある混乱の原因となるのが、Auth インターフェース と Connect インターフェースの使い分けです。どちらも似たようなパターンのログイン機能を提供するためです。しかし、それぞれ特定の目的を持っています。

Auth インターフェース
・Auth インターフェースは、Epic アカウントへの認証を処理します。そのため、Epic アカウントサービス が設定されている必要があります。
・Auth インターフェースを介した認証は、EOSのフレンド、プレゼンス、Eコマース機能へのアクセスを提供します。
・Auth インターフェースは一意のEpic アカウント ID を使用します。
Connect インターフェース
・Connect インターフェースは、Epic ゲームサービスへの認証を処理します。このインターフェースはプロバイダに依存しないため、さまざまな ID プロバイダ(Epic Games、Steam、Xbox Live など)で使用することができます。
・Connect インターフェースは Epic アカウントに依存しません。その代わりに、組織内の特定の製品の一意の製品ユーザーID(PUID)を使用します。

簡単に言えば、Authインターフェースは Epic アカウントと関連するソーシャルグラフAPIを処理する一方、Connect インターフェースは、ゲームに代わって作成され、外部ID とリンクする必要のある、一意のユーザーIDを処理するということです。Connect インターフェースで使用されるIDはソーシャルグラフではないため、複数のIDに接続されたクロスプレイやクロスプログレッションに使用することができ、Auth インターフェースなしで使用することができます。

さらにもう一つ引用します。

Connect インターフェースを使用して EOS ゲーム サービスにアクセスする - Epic Online Services

Auth インターフェースと Connect インターフェースの比較 (概要)
これらのインターフェース間の違いについては、Epic アカウント サービス (EAS) での認証 の記事で詳しく解説しました。その概要は、Auth インターフェース は Epic アカウントを認証して、プレゼンスやフレンド情報で Epic アカウント サービスを使用する、さらに Epic Games ストアで購入するために使用されます

Connect インターフェース は今後このシリーズで使用するもので、使用する製品の各プレイヤーに対する固有の製品ユーザー ID (PUID) を生成し、マルチプレイヤー、進行状況、ゲームの運用をカバー するゲーム サービスを使用します。これらはそれぞれ独立して使用でき、Connect インターフェースは サポート対象の ID プロバイダ とともに使用できます。Epic アカウントを使用する必要はありません。

ここまでで、EAS が Stema アカウントや PSN のアカウントと同等であることは間違いなさそうです。特にフレンド等のソーシャルグラフ、ストアでの購入情報などは各プロバイダが保有するものなので、そこは EOS がどうこうできるものではないと思われます。

そして EOS は EAS とは全く関係がなく、EAS も含めてプロバイダと製品を連携し、Epic ゲームサービスの機能を利用可能にすることができます。
よって、EOS の多くのサンプルでは EAS での例が多いですが、EAS を利用せず、Steam アカウントのみで EOS にログインすることが可能です。

最後に上記ページからもう一つ引用します。

このサンプル アプリでは、Epic アカウントを使用する Connect API インテグレーションを実装します。このコードは実装済みだからです。ただし、先に進む前に、サポート対象 ID プロバイダを使用するために、どのようなフローで実装されているのかを順に確認します。

  1. ゲームでプレイヤーに確認するのは、ID プロバイダ (A) を使用して Connect.Login() を通じて認証するかどうかです。
  2. 指定 ID プロバイダで対象プレイヤーに対する製品 ID (PUID) が見つかった場合、このコールバックの ResultCode が Result.Success になり、コールバックが PUID を LocalUserId メンバーに返します。
  3. . PUID が見つからない場合、ResultCode が Result.InvalidUser になり、コールバックは ContinuanceToken を返します。この時点で、複数の ID プロバイダをサポートしている場合に、プレイヤーが他のサポート ID プロバイダを使用して認証するかどうかをプレイヤーに確認できます。 これを実行するのは、セカンド PUID が作成され、進行状況データが新しいものとしてそれに関連付けられないようにするためです。この場合は後でアカウントをマージする必要があります。他の方法として、この ID を引き続き使用するのかを確認します (それから新しい PUID を作成)。
  4. ユーザーがこの ID をそのまま使用することを希望する場合、Connect.CreateUser() を使用して、ContinuanceToken を CreateUserOptions を通じて渡します。このとき ResultCode が Result.Success であれば、PUID が LocalUserId メンバーに見つかります。
  5. ユーザーが異なる ID プロバイダ (B) での認証を希望する場合、この ContinuanceToken を保存し、再び Connect.Login() を ID プロバイダ B を使用して呼び出します。ログインに成功した後、両方の ID をリンクするかどうかをユーザーに確認できます。Connect.LinkAccount() を呼び出して、両方のアカウントが同じ PUID に関連付けられていることを確認します。

例えば、ID プロバイダを最初は Steam を利用していたとします。
ここで、ある PC ゲームに対して、Steam でログインし、すでにプレイしていれば OK です。 (上記 1, 2)
もしそれが初回のプレイの場合は、 PUID が存在しないため、InvalidUser となります。 (上記 3)
このゲームを他のプロバイダのアカウント (Epic アカウントや PSN のアカウントなど)でプレイしたことがなければ、新規に PUID が作成されます。(上記 4)
逆に、そのゲームを Epic アカウント等の別の外部アカウントでプレイしたことがあった場合には、 その別の外部アカウントでログインするかを確認されます。(実際には、サポートするあらゆるプロバイダが一覧されるはず)
そして、その別の外部アカウントと、Steam アカウントをリンクするかを確認されます。(上記 5)

おそらく、ここでリンクしてしまえば、今後はどちらのアカウントでログインしたとしても内部的にはそのゲームで同じ PUID が利用されることになりそうです。
これができると、コンソールをまたがっていたとしても、共通の PUID が利用できるということになりそうです。(ただ、おそらくは主要なアカウントが一つあって、そこに対して認証を追加できる形になるのかなと 🤔でないと、プレイ実績はともかく、購入品の管理なんかは難しそうなので)

まとめ

では最後に当初の疑問を解消する形で締めておきます。

  • EOS Connect インターフェースでのログインはどういうことか
  • EOS_EpicAccountIdEOS_ProductUserId はどのように違うのか

前者に関しては、EOS Connect インターフェースでログインすることで、その製品(つまりゲーム)で EOS の機能を利用可能にします。
EOS にログインするためには、何らかの外部資格情報が必要になり、それが Steam アカウントであったり、Epic アカウントであったりします。

また、EOS としては、製品ユーザーID で製品とユーザーを紐付けて管理しています。これは、一つの外部資格情報のユーザーであっても製品が異なれば製品ユーザーIDは異なるということです。

正直、コードを書いてみないと腹落ちしない感じはしますが、一旦この辺にしておきます。

前回の追記

今回の整理を受けて改めて前回の EOS_P2P_ReceivePacket の引数に EpicAccountId が渡されているのはおかしいのではないかと思い見直してみましたが、単にサンプルでは以下のように TEpicAccountId という構造体をEOS_EpicAccountIdEOS_ProductUserId の両方の wrapper として利用しており、値のプロパティが AccountId であるため、読み違えてしまったというだけでした。

using FEpicAccountId = TEpicAccountId<EOS_EpicAccountId>;
using FProductUserId = TEpicAccountId<EOS_ProductUserId>;

なので、EOS_P2P_ReceivePacket の引数で渡されていたのは、EOS_ProductUserId でした。