GS2 Blog

Game Server Services(https://gs2.io/) の最新情報をお届けします

GS2-Inbox のグローバルメッセージに受取可能期間を設定できるようになりました

はじめに

GS2-Inbox はゲーム内のプレゼントボックス機能を実現するためのマイクロサービスで、すべてのプレイヤーにプレゼントを配布するための仕組みとしてグローバルメッセージ機能があります。

グローバルメッセージ機能はマスターデータでメッセージデータを定義し、プレイヤーがグローバルメッセージの受信APIを呼び出すと各プレイヤーのプレゼントボックスにメッセージデータをコピーして実体化することで実現しています。

機能追加の背景

グローバルメッセージをプレイヤーに届けるにあたって、マスターデータに定義したら即座に配送対象となり、送信の予約はできませんでした。

追加された機能の詳細

「運営上、配信日時の予約設定をしたい」というお声を頂戴することがあり、グローバルメッセージに GS2-Schedule のイベントを関連づけられるようにしました。

グローバルメッセージのマスターデータに GS2-Schedule のイベントを関連づけることで、イベントの開催期間にグローバルメッセージの受信APIを呼び出した時にのみメッセージがコピーされるようになりました。

GS2-Schedule の相対期間イベントに絶対期間を組み合わせられるようになりました

はじめに

GS2-Schedule はゲーム内のイベント開催期間を管理するマイクロサービスです。

なかでも、相対期間イベントとはプレイヤーごとに異なるイベント期間を設定するもので、チュートリアル突破後24時間を特別な期間とするような仕様を実現するために使用できます。

機能追加の背景

相対期間イベントはトリガーを引くAPIを呼び出して、そこから一定期間をイベント期間とすることができます。
このイベント期間はトリガーを引けば必ず発動し、トリガーを引いたとしても 2024年1月1日〜2024年1月3日 の間しか相対期間イベントとするような設定ができませんでした。

この課題を解消するための変更が今回のアップデートです。

追加された機能の詳細

イベントのマスターデータにはイベントの期間設定として「絶対期間」「相対期間」をまず選択します。
絶対期間の場合はイベントの開催期間を絶対値で、相対期間の場合はトリガーの名前を指定しました。

今回の更新で「相対期間」を設定した時にも、開催期間を絶対値で指定するオプションが追加されました。

この更新はイベント開催期間の判定ロジックにのみ影響し、ゲーム内からのAPI仕様には特に影響ありません。

ギルド機能の提供を開始しました

はじめに

ゲームにはプレイヤー同士が長期の協力プレイをするための仕組みとして、ギルドやクランという仕組みが導入されるケースがあります。
GS2 にはこれまでこのような仕組みを実現する方法がありませんでした。

追加された機能の詳細

新しく追加された GS2-Guild はギルドメンバーの管理と、ギルドに関する情報を紐づけるためのギルドユーザーの仕組みを提供します。

ギルドユーザー

GS2-Guild では、ギルドレベルやギルドメンバーで共有するインベントリを実現するために「ギルドユーザー」という仕組みを持ちます。
ギルドユーザーは GS2 のいちアカウントとして処理され、全ての GS2 のマイクロサービスを使ってこのギルドユーザーに紐づくプロパティを管理できます。

従来のGS2-Accountのユーザーはパスワードを使ってログインしますが、ギルドユーザーはパスワードではログインできません。
その代わり、GS2-Guild にユーザーフェデレーションの仕組みが用意されています。

ユーザーフェデレーションは、ギルドメンバーのアクセストークンを用いて、ギルドユーザーのアクセストークンを取得する仕組みです。
この仕組みによって、ギルドメンバーはギルドユーザーのアクセストークンを取得することで、ギルドユーザーに紐づくレベルを取得したり、インベントリの操作が可能となります。

ロール

次に、ギルドの特徴としてギルドメンバーごとに権限管理できるようになっていることです。
具体的にはギルドマスターのようなギルドを管理する立場のプレイヤー向けの権限と、ギルドメンバー向けのギルドで活動はするが管理する権限は持たないようなプレイヤー向けの権限を設定できます。

ロールの権限の内容はゲーム開発者自由に定義することができ、さらにプレイヤーが自由にロールを作成できるカスタムロールの仕組みも有しています。

ユーザーフェデレーションをする際にメンバーに割り当てられたロールに基づく権限でギルドユーザーとして実行できるAPIを絞り込むことができるようになっています。

ポリシー

権限は GS2-Identifier のポリシードキュメントフォーマットを用いて定義します。
具体的な例として、ギルドの管理権限とギルドユーザーの GS2-Experience のAPIを呼び出す権限を付与するとしましょう。

{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Guild:Describe*",
        "Gs2Guild:Get*",
        "Gs2Guild:AcceptRequest",
        "Gs2Guild:RejectRequest",
        "Gs2Guild:DeleteMember",
        "Gs2Gateway:SetUserId",
        "Gs2Experience:*"
      ],
      "Resources": ["*"]
    }
  ]
}

前半の 「Gs2Guild」で始まる部分がギルドユーザーとして実行可能なAPIを宣言する部分で、メンバー管理に必要なAPIが指定されています。
「Gs2Gateway:SetUserId」にはギルドユーザーに関する通知を受け取れるようにする権限設定です。
この宣言がないと通知を受け取ることができず、ギルドへの参加申請が届いたことや、ギルドユーザーに関するプロパティの変化をアプリが知ることができなくなります。
最後の「Gs2Experience:*」が GS2-Experience の全てのAPIを呼び出す権限を付与する部分です。

さて、ここで 「Gs2Experience:*」と書いてしまうと、「Gs2Experience:AddExperienceByUserId」 のような任意のプレイヤーに任意の経験値を付与するAPIを呼び出せるようになるのでは?と不安に思うかもしれません。
しかし、ユーザーフェデレーションをする場合、フェデレーションする前のアクセストークンが持つ権限より強い権限を得ることはできません。
そのため、一般的なゲームプレイヤーが持つであろう「ApplicationAccess」権限では元々「Gs2Experience:AddExperienceByUserId」を呼び出すことはできませんので、ロールのポリシードキュメントに全てのAPIを呼び出せるように記述したとしても、「Gs2Experience:AddExperienceByUserId」を呼び出せるようにはなりません。

ちなみに、余談として申請の承認やギルドメンバーの除籍APIを呼び出せない、一般的なギルドメンバーの権限は以下のように設定します。

{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Guild:Describe*",
        "Gs2Guild:Get*",
        "Gs2Gateway:SetUserId",
        "Gs2Experience:*"
      ],
      "Resources": ["*"]
    }
  ]
}

GS2-Showcase でギルドマスターだけがギルドユーザーとして商品を買えるようにしたければ、ギルドマスターのロールにだけ「Gs2Showcase:Buy」をつけるといった対応をすることで細やかな権限管理ができます。

参加承認

権限管理のセクションで軽く触れましたが、GS2-Guild のギルドには参加するために既存のギルドメンバーから承認を得る必要があります。
ただし、ギルド作成時に「参加方針」を「自由参加」に設定することで、ギルドに参加申請を出すと直ちにギルドに参加することができます。

参加人数の上限

GS2-Guild には参加人数の上限を設定できます。
この参加人数はギルドごとに個別に引き上げることができます。
この仕組みを使うことで、ギルドレベルが上がることで参加可能なプレイヤー数を増やすような仕様を実現できます。

ギルドの検索

プレイヤーがギルドを見つけるための仕組みとして、ギルドの検索機能があります。
検索条件には主に4つの要素を指定できます。

表示名

ギルドの表示名の部分一致で絞り込むことができます。

参加方針

ギルドの参加方針が「自由参加」か「承認制」かで絞り込むことができます。

属性値

ギルドには最大5個の属性値を設定できます。
属性値は整数値で、検索条件には完全一致の条件を最大10種 OR で指定できます。
「ガチプレイ」「まったりプレイ」のようなギルドの運営方針や、ゲーム内の「所属国家」などで絞り込むことを想定しています。

参加人数

最後の条件はギルドの参加人数が上限に達しているギルドを除外することができます。
プレイヤーは原則新しく参加するためのギルドを探すために検索をしているでしょうから、満員のギルドは除外する方が合理的かもしれません。
一方で、プレイヤーが表示名で絞り込んでいる場合は友達の所属しているギルドを探しているのかもしれません。その時検索結果にまったく表示されないとプレイヤーは困惑してしまう可能性があります。
UXを考慮しつつこの条件を指定できるよう、検索のパラメーターとしてこの値を指定できるようにしています。

実装例

ギルドを作成

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CreateGuildAsync(
        guildModelName: "guild-model-0001",
        displayName: "My Guild",
        joinPolicy: "anybody",
        attribute1: 1,
        attribute2: null,
        attribute3: null,
        attribute4: null,
        attribute5: null,
        customRoles: null,
        guildMemberDefaultRole: null
    );
    var item = await result.ModelAsync();

ギルドを検索

    var items = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SearchGuildsAsync(
        guildModelName: "guild-model-0001",
        displayName: "My Guild",
        attributes1: new int[] { 0, 1 },
        attributes2: null,
        attributes3: null,
        attributes4: null,
        attributes5: null,
        joinPolicies: null,
        includeFullMembersGuild = null
    ).ToListAsync();

ギルドに参加リクエストを送信

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestAsync(
        guildModelName: "guild-0002",
        targetGuildName: "guild-0002"
    );

送信した参加リクエストの一覧を取得

    var items = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestsAsync(
        guildModelName: "guild-0002"
    ).ToListAsync();

参加リクエストを取り下げ

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CancelRequestAsync(
        guildModelName: "guild-0002",
        targetGuildName: "guild-0002"
    );

ギルドユーザーとしてアクセスするためのゲームセッションを取得

    var guildGameSession = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).AssumeAsync(
        guildModelName: "guild-model-0001",
        guildName: "guild-0001"
    );

受信した参加リクエストの一覧を取得

    var domain = gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).GuildGameSession(
        guildModelName: "guild-0001",
        guildGameSession: guildGameSession
    );
    var items = await domain.ReceiveRequestsAsync(
    ).ToListAsync();

参加リクエストを承認

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    )->GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    ).ReceiveMemberRequest(
        fromUserId: "user-0001"
    ).AcceptRequestAsync(
    );

参加リクエストを否認

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    )->GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    ).ReceiveMemberRequest(
        fromUserId: "user-0001"
    ).RejectRequestAsync(
    );

関連ドキュメント

docs.gs2.io

リソースレベルのアクセス制御ができるようになりました

はじめに

GS2-Identifier は GS2 のAPI呼び出しのための権限管理をするためのサービスです。
プロジェクトに対して複数のクレデンシャル(APIキー)を発行でき、それぞれに呼び出し可能なAPI権限を設定できます。

機能追加の背景

これまでは、呼び出し可能なAPIの種類のみが制御可能でした。
今回のアップデートでは、そこから更にリソース単位でのアクセス制御が可能となりました。

例えば、クレデンシャルAは 「GS2-Account でアカウントを作成する権限がある」 というような設定しかできなかったのが
「GS2-Account のネームスペース1 にアカウントを作成する権限がある」というような設定が可能となりました。

機能追加の詳細

今回の機能追加により、これまでであればチートに繋がる恐れがあるため推奨できなかった
クライアントアプリケーションから GS2-Script をプレイヤーが任意のタイミングで実行しても問題ないように実装されたスクリプトスクリプトのみをAPIの呼び出し権限に加えることができます。

制限の適用方法

{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Inbox:*"
      ],
      "Resources": [
        "*"
      ]
    }
  ]
}

これまで Resouces セクションには "*" しか指定できませんでした。
しかし、今回のアップデートで操作を許可または拒否する grn を指定できるようになりました。

Actions と同様にワイルドカード(*)を先頭または末尾に追加できます。

例えば、GS2-Script に 「namespace1」 と 「namespace2」 があり、namespace2 のスクリプトのみをクライアントから直接呼び出せるように設定したい場合は

{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Script:InvokeScript"
      ],
      "Resources": [
        "grn:gs2:ap-northeast-1:your-owner-id:script:namespace2:*"
      ]
    }
  ]
}

と指定したポリシーをクレデンシャルに割り当てることで、実現ができます。
GRNの値はマネージメントコンソールで確認したり、権限がない状態でAPIを呼び出すことでエラーメッセージで権限の不足しているGRNの確認が可能です。

より詳しいドキュメントは以下を参照してください。

docs.gs2.io

GS2-Account の認証時のスクリプトに前回ログインからの経過時間が渡るようになりました

はじめに

GS2-Account はゲームが必要とする認証機能を提供するサービスです。

機能追加の背景

「久しぶりゲームを再開してくれたプレイヤーにカムバックボーナスを付与したい」というようなニーズがあります。
このようなニーズを満たすために認証時のスクリプトに前回ログインからの経過時間を渡すようにし、スクリプトから GS2-Schedule のカムバック用のイベントを開始状態にすることで、カムバック時にのみ得られる報酬を設定できます。

追加された機能の詳細

namespace = args.namespace
account = args.account
elapsedHours = args.elapsedHours

result = {
}

GS2-Account の認証時のスクリプトの引数に「elapsedHours」が追加されました。
この値を使って判定してください。

GS2の各種パラメーターに補正値を適用する GS2-Buff が公開されました

はじめに

GS2 はさまざまなマスターデータやユーザーデータを取り扱います。
イベントやサブスクリプションの特典として、各種パラメーターに補正値を適用したいことがあります。

例えば、イベント期間中は「スタミナ消費量半減」「クエスト報酬2倍」「スタミナ最大値2倍」というようなことです。

新サービス追加の背景

これまではこのような補正値を適用する手段がなく、マスターデータをイベント期間のみ差し替えるような対応が必要でした。
しかし、マスターデータの更新は予約することができないため、メンテナンス期間をとってメンテナンスとしてマスターデータの更新作業を行うようなオペレーションが必要でした。

新サービスの詳細

GS2のさまざまなパラメーターに対して補正値を適用できるようになり、なおかつ補正値は GS2-Schedule が管理するイベントの期間と連動させることができます。
これにより、メンテナンス期間をとったりマスターデータを更新するオペレーションをすることなく、値の補正を行えるようになりました。

バフエンティティ

各マイクロサービスに加える補正の単位です。 基礎値を 1.0 として、各パラメータに対してどの程度増減させるかを定義します。 補正値の定義方法は「Add」と「Mul」が用意されており、Add 1.5 とすると補正値は2.5倍に、Mul 1.5 とすると補正値は1.5倍になります。

適用優先度

補正値には適用優先度を設定できます。優先度に設定された値が小さい補正値から順番に補正値の計算が行われます。 たとえば、以下の補正値が定義されていたとします。

補正値の種類 補正値 適用優先度
Add 0.2 1
Mul 1.5 2
Add 0.2 3

この場合、以下の順番で補正値の計算が実行されます。

1.0 + 0.2 = 1.2
1.2 * 1.5 = 1.8
1.8 + 0.2 = 2.0

そして、最終的な補正値は 2.0倍 となります。

補正の適用範囲

バフの適用範囲は広範囲で、マスターデータの取得APIでもバフが適用されます。

バフの適用方法

    gs2 = await gs2.Buff.Namespace(
        "buff"
    ).Me(
        GameSession
    ).Buff().ApplyBuffAsync();

    // 新しい gs2 オブジェクトを通してアクセスするとバフがかかった値で処理される

詳細は以下のドキュメントを参考にしてください

docs.gs2.io

GS2-Inventory の巨大インベントリのアイテム入手・消費時のスクリプトを実装できるようになりました

はじめに

GS2-Inventory はアイテムの所持数量を管理するマイクロサービスです。
なかでも巨大インベントリは 64bit整数値 の範囲を超えるアイテムの所持数量を管理するマイクロサービスです。

クッキークリッカーを代表するインフレ系ゲームのようなゲームでクッキーの所持数量を管理するために利用できます。

今回の更新で解消された課題

これまで巨大インベントリのアイテム入手・消費時のスクリプトは設定できませんでした。

追加された機能の詳細

新しく巨大インベントリのアイテム入手・消費時のスクリプトを設定できるようになりました。
スクリプトの戻り値では、処理を継続するかに加えて、入手量・消費量の対して倍率による補正をかけられるようになりました。

result = {
  permit=true,
  rate=1.5
}

のようにスクリプトを設定することで、報酬の量を1.5倍にすることができます。
ただし、巨大インベントリが扱う値の性質上若干の計算誤差が生じます。

(C) Game Server Services, Inc.