NAV
Unity Unreal Engine 4

Game Server Services

Game Server Services (GS2) is a back-end server service (BaaS) specialized for mobile game development.

The network functions required for game development are componentized and provided as a service.
It is designed to be used from within the game in units of some of the necessary components, allowing easy, affordable, and high-performance server functionality.

Pricing

Individual plan

Corporations or individuals with sales of less than 10 million JPY in the past 12 months may use all features free of charge.
(This includes sales from other businesses, not sales from games using GS2)

This does not apply if the average number of requests per month exceeds 10 requests per second or 100 requests per second continuously for a certain period of time.
In such cases, we will still consider the time required to modify the application, but please respond promptly.

Professional plan

Based on the following rates for sales of 10 million JPY or more in the past 12 months.

General usage fees

Unless otherwise noted in the service, the following rates are available

Free tier

The service is free of charge until the amount exceeds 20,000 JPY.
Once the amount exceeds 20,000 JPY, you will be billed for the entire amount used, not just the excess.

Enterprise plan

All features can be used for a fixed amount of 30 JPY to 150 JPY per MAU (determined by the degree to which the game depends on the server).
The actual usage fee will be billed at the "lower" price compared to the Professional plan.

Please contact GS2 if you wish to use this service.

Processing performance

GS2 is designed to make game servers performance-conscious.
Pre-release benchmarks confirm that it can handle 100,000 accesses per second.

However, it is difficult to provide all APIs without having to worry about performance.
Some APIs may have a separate line of performance guarantee.
Where separate performance guarantees are defined, they are defined for each component.

Getting Started

Introduction

In this section, you will learn how to create a Unity / Unreal Engine 4 project to take advantage of the GS2 features.

  1. Configuration procedure in the GS2 management console
  2. Instructions for integrating GS2 SDK for Game Engine into Unity / Unreal Engine 4 projects

The following is a summary of the following information.

Create a GS2 account

First, register for a GS2 developer account from the GS2 website.

After registration, you will receive an email confirming your email address.

After accessing the URL and verifying your email address, click Log-in to the Management Console with your registered account information.

Create a project

Create a project in the Management Console.

The project is paired with a development game title.
GS2 resources (configured content, master data, etc.) are maintained on a project-by-project basis.
It cannot interfere with the resources of other projects.

You can create a Project either when you start creating a new game title or in the middle of development.

  1. Log-in to the Management Console.
  2. Open the Project > List of Projects page.
  3. Click Create New Project.
  4. Enter a project name and description and click Create.

Only upper and lower case alphanumeric characters, hyphens, and underscores are allowed in project names.
e.g. MySuperCool_Stg_Game-001

Add authentication information

Add credentials (authentication information) to the project.

Applications can access various APIs by performing GS2-Identifier authentication using the client ID and client secret information contained in the Credential.

Authentication is performed on a GS2-Identifier User basis.
The GS2-Identifier User has the definition of privileges to use GS2 services.
In this section, we will add a user with access privileges for applications.

  1. On the left side of the Management Console, select Identifier and click on Users.
  2. The Identifier > List of User' page will open. SelectCreate a new user` on the right side.
  3. The Identifier > List of User > Create a new User page will open. Fill in the username and description fields as appropriate, and click Create (e.g. username : Application, etc.).
  4. On the Identifier > List of User page, select the user you just created.
  5. On the Identifier > User List > User Information' page, add a __Credential__ to theuser. On theCredentialstab, clickCreate New Credential`.
  6. On the Identifier > User List > User Information > Credential > Create new credential' page, clickCreate' to issue a Client Id and Client Secret.
    Please keep the issued Client Id and Client Secret at hand.
  7. Assign the Security Policy to the newly created user.
    We will assign a security policy called ApplicationAccess, which has already been defined as a standard application access policy.
    Click the Assign button for the security policy name ApplicationAccess on the Security Policy tab of the Identifier > List of User > User Information page.

The application is now ready to access the GS2 project.

Configuration by GS2-Deploy

Users and credentials can be added from the GS2-Identifier administration screen.
GS2-Deploy makes it easier.

GS2-Deploy is a service designed to achieve continuous delivery.
You can use code written in YAML format to automatically build resources.

For example, if you create a stack using a template that adds a new user
New users can be added to GS2-Identifier automatically.

About Stacks

GS2-Deploy is a Template (which describes the steps on how to manipulate and build the resources in GS2)
The resources of each service are actually manipulated based on the
The aggregate of the resources built with this template is called a stack.

Reapplying a template with modified content to a stack causes the update to be processed.
The differences in changes are detected, and any new resources that need to be created are created as new resources, and any new resources that need to be created are created as new resources.
Resources that need to be updated are updated, and resources that need to be deleted are automatically deleted for each resource.
This mechanism eliminates the need for developers to delete resources that are no longer needed.
The desired resource status can be automatically built simply by describing it in a template.

Now let's actually create a stack using the template.

Example GS2-Deploy template for issuing credentials (in YAML format)

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10

Globals:
  Alias:
    ApplicationUserName: application

Resources:
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}

  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser

Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret

The example shows a sample template that creates a user with ApplicationAccess privileges.
The user name created for GS2-Identifier can be changed by changing the ApplicationUserName: application part.

Download Template

Save this template file, and in GS2-Deploy's Create a new stack
Create a stack by specifying it as template data.

The status of settings registered in the created stack can be checked in the Execution Status section of the stack.
After a few seconds, CREATE_COMPLETE and credential configuration is complete.

After the reflection is complete, select the Output tab.
The credential 's Client ID and Client Secret are displayed.
This value will be set later on the game app side.

Download and install GS2 SDK for Game Engine

GS2 SDK for Unity or GS2 SDK for Unreal Engine 4 is available from GS2 SDK for Game Engine.
Download the appropriate package for your environment and follow the instructions provided.

You are now ready to use GS2 in your game application.

Procedures for Implementing Account Management Functions

The following is a guide on how to implement a login process using the GS2-Identifier and GS2-Account services in a game application.
This section explains with sample code.

Download sample code (Unity)

After creating a new project and installing GS2 SDK for Unity
Create an empty game object or other object in your scene and add a GS2AccountSample component.

Download sample code (Unreal Engine 4)
The project name is the source code for the MyProject environment.
Replace MyProject with the project name in the source as appropriate, and then execute.

GS2-Account Settings

To start using GS2-Account service, you need to You will need to add a namespace.

A namespace is a place where the same service can be used within a single project.
It is a mechanism for making it possible to use a product for multiple different purposes.
Within different namespaces, the same service is treated as completely different data space.

Now, let's use the example template to create a
Add game-0001 to the GS2-Account namespace name, issue the encryption key used to authenticate the account, and
New accounts can be created.

In GS2-Deploy's [Create a new stack]](https://app.gs2.io/deploy/stack/create), click
Create a stack by specifying the following template as template data

Download Template

Template for getting started with GS2-Account

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2-Account initialize template Version 2010-06-26

Globals:
  Alias:
    AccountNamespaceName: game-0001
    KeyNamespaceAccountAuthentication: account-encryption-key-namespace
    KeyAccountAuthentication: account-encryption-key

Resources:
  KeyNamespaceAccountAuthentication:
    Type: GS2::Key::Namespace
    Properties:
      Name: ${KeyNamespaceAccountAuthentication}

  KeyAccountAuthentication:
    Type: GS2::Key::Key
    Properties:
      NamespaceName: ${KeyNamespaceAccountAuthentication}
      Name: ${KeyAccountAuthentication}
    DependsOn:
      - KeyNamespaceAccountAuthentication

  AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: ${AccountNamespaceName}

Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
  KeyAccountAuthenticationKeyId: !GetAttr KeyAccountAuthentication.Item.KeyId

Initialization of GS2 SDK

// Initialize GS2 SDK client

Debug.Log("Initialize GS2 SDK client");

var profile = new Gs2.Unity.Util.Profile(
    clientId: clientId,
    clientSecret: clientSecret,
    reopener: new Gs2BasicReopener()
);

{
    AsyncResult<object> asyncResult = null;

    var current = profile.Initialize(
        r => { asyncResult = r; }
    );

    yield return current;

    // The callback is always called when the execution of the coroutine finishes

    // Exit if client initialization fails
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }
}

var gs2 = new Gs2.Unity.Client(profile);
ProfilePtr = std::make_shared<gs2::ez::Profile>(
    TCHAR_TO_ANSI(*ClientId),
    TCHAR_TO_ANSI(*ClientSecret),
    gs2::ez::Gs2BasicReopener()
);

ClientPtr = std::make_shared<gs2::ez::Client>(
    *ProfilePtr
);

ProfilePtr->initialize(
    [this](gs2::ez::Profile::AsyncInitializeResult r)
    {
        if (r.getError())
        {
            // Exit if client initialization fails
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.initialize failed.");
        }
        else
        {
            AccountCreate();
        }
    }
);

The sample code initializes the utility class Profile for access to GS2.

Set clientId clientSecret to the credentials of the target user for access.
The actual value is the same as the value of the stack created using GS2-Deploy in Add Authentication Information.
Set the value of ApplicationClientId ApplicationClientSecret, which can be found on the Output tab.

AccountNamespaceName KeyAccountAuthenticationKeyId Similarly, the account management stack's
Set the contents of the Output tab.

The reopener sets the handler for refreshing the access token.
Here, Gs2BasicReopener is set.

Create a new account

// Create new account

Debug.Log("Create new account");

EzAccount account = null;

{
    AsyncResult<EzCreateResult> asyncResult = null;

    var current = gs2.Account.Create(
        r => { asyncResult = r; },
        accountNamespaceName
    );

    yield return current;

    // The callback is always called when the execution of the coroutine finishes

    // Exit if account could not be created
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    // Retrieve created account information
    account = asyncResult.Result.Item;
}
ClientPtr->account.create(
    [this](gs2::ez::account::AsyncEzCreateResult r)
    {
        if (r.getError())
        {
            // Exit if account could not be created
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.create failed.");
        }
        else
        {
            // Retrieve created account information
            EzAccount = r.getResult()->getItem();

            ProfileLogin();
        }
    },
    TCHAR_TO_ANSI(*AccountNamespaceName)
);

Here we are creating an account to identify the game player.
accountNamespaceName is the name of the namespace to which the account will be added.
Set the value of AccountNamespaceName on the Output tab of the account management stack.

The Create method callback is called when the account creation process is complete.
If an error occurs, an exception object is stored in r.Error and
On success, the result is stored in r.Result.

Note that this sample logs in with a new account on every startup.
Normally, an account is created only when the application is launched for the first time.
In the actual application, this response account information is stored in local storage, etc., and
The second and subsequent times, the account information is retrieved from local storage, etc., and used to create a new account.
Log in as an existing game player.

Login process

// Login

Debug.Log("Login");

GameSession session = null;

{
    AsyncResult<GameSession> asyncResult = null;
    var current = profile.Login(
       authenticator: new Gs2AccountAuthenticator(
           session: profile.Gs2RestSession,
           accountNamespaceName: accountNamespaceName,
           keyId: accountEncryptionKeyId,
           userId: account.UserId,
           password: account.Password
       ),
       r => { asyncResult = r; }
   );

    yield return current;

    // The callback is always called when the execution of the coroutine finishes

    // Exit if game session object could not be created
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    // Obtain a game session object representing the login state
    session = asyncResult.Result;
}
ProfilePtr->login(
    [this](gs2::ez::Profile::AsyncLoginResult r)
    {
        if (r.getError())
        {
            // Exit if game session object could not be created
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.login failed.");
        }
        else
        {
            // Get a game session object representing the login state
            GameSession = *r.getResult();

            AccountListTakeOverSettings();
        }
    },
    gs2::ez::Gs2AccountAuthenticator(
        ProfilePtr->getGs2Session(),
        TCHAR_TO_ANSI(*AccountNamespaceName),
        TCHAR_TO_ANSI(*AccountEncryptionKeyId),
        EzAccount.getUserId(),
        EzAccount.getPassword()
    )
);

The next step is to log in to GS2.
For accountNamespaceName, specify the name of the namespace where the account you created exists, and for keyId specifies the encryption key used to calculate the signature to be given to the account's authentication result.
In addition, userId password specifies the user ID and password for the created account.

When the login process is complete, the callback is called and an exception object is stored in r.Error in case of an error, and the result is stored in r.Result in case of success.

Resultreturns aGameSessionobject to represent the login state. From now on, when calling GS2 APIs, you must passGameSession` as an argument for APIs that can only be called when you are logged in.

Callable API calls after login

// Get list of takeover information

Debug.Log("Get list of takeover information");

{
    AsyncResult<EzListTakeOverSettingsResult> asyncResult = null;

    var current = gs2.Account.ListTakeOverSettings(
        r => { asyncResult = r; },
        session,
        accountNamespaceName,
        30,
        null
    );

    yield return current;

    // callback is always called when the execution of the coroutine is finished

    // Callback notified when API call completes
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    List<EzTakeOver> items = asyncResult.Result.Items;
    foreach (var item in items)
    {
        // Information about the takeover is retrieved.
    }
}
ClientPtr->account.listTakeOverSettings(
    [this](gs2::ez::account::AsyncEzListTakeOverSettingsResult r)
    {
        if (r.getError())
        {
            // Exit if the list of transfer information could not be obtained
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.listTakeOverSettings failed.");
        }
        else
        {
            auto& items = r.getResult()->getItems();
            for (auto i = 0; i < items.getCount(); ++i)
            {
                // Information about the transfer is retrieved.
            }

            ProfileFinalize();
        }
    },
    GameSession,
    TCHAR_TO_ANSI(*AccountNamespaceName)
);

As an example of an API that can only be used while logged in, we call the API to retrieve a list of takeover settings.
You can retrieve the list of handover settings set for a currently logged-in game player by passing GameSession as the session.

GS2 SDK termination process

// GS2 SDK termination process

Debug.Log("GS2 SDK termination process");

{
    // Call this when exiting a game, for example.
    // Calling it frequently is not expected.
    var current = profile.Finalize();

    yield return current;
}
void AMyActor::ProfileFinalize()
{
    // GS2 SDK termination process

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.finalize");

    // Call this when exiting a game, for example.
    // Not intended to be called frequently.
    ProfilePtr->finalize(
        [this]()
        {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, "successfull.");
        }
    );
}

Termination of the Profile class.
Terminates the connection with GS2.

Full sample code

The entire sample code is shown in the code section.

using System;
using System.Collections;
using System.Collections.Generic;
using Gs2.Core;
using Gs2.Unity.Gs2Account.Model;
using Gs2.Unity.Gs2Account.Result;
using Gs2.Unity.Util;
using UnityEngine;

public class GS2AccountSample : MonoBehaviour
{
    // Client ID issued by GS2-Identifier
    public string clientId;

    // Client Secret issued by GS2-Identifier
    public string clientSecret;

    // Namespace name of the GS2-Account in which to create the account
    public string accountNamespaceName;

    // The encryption key used to compute the signature to be assigned to the account's authentication result.
    public string accountEncryptionKeyId;

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(CreateAndLoginAction());
    }

    public IEnumerator CreateAndLoginAction()
    {
        // Initialize GS2 SDK client

        Debug.Log("Initialize GS2 SDK client");

        var profile = new Gs2.Unity.Util.Profile(
            clientId: clientId,
            clientSecret: clientSecret,
            reopener: new Gs2BasicReopener()
        );

        {
            AsyncResult<object> asyncResult = null;

            var current = profile.Initialize(
                r => { asyncResult = r; }
            );

            yield return current;

            // The callback is always called when the execution of the coroutine finishes

            // Exit if client initialization fails
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Client(profile);

        // Create new account

        Debug.Log("Create new account");

        EzAccount account = null;

        {
            AsyncResult<EzCreateResult> asyncResult = null;

            var current = gs2.Account.Create(
                r => { asyncResult = r; },
                accountNamespaceName
            );

            yield return current;

            // The callback is always called when the execution of the coroutine finishes

            // Exit if account could not be created
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // Retrieve created account information
            account = asyncResult.Result.Item;
        }

        // Login

        Debug.Log("Login");

        GameSession session = null;

        {
            AsyncResult<GameSession> asyncResult = null;
            var current = profile.Login(
               authenticator: new Gs2AccountAuthenticator(
                   session: profile.Gs2RestSession,
                   accountNamespaceName: accountNamespaceName,
                   keyId: accountEncryptionKeyId,
                   userId: account.UserId,
                   password: account.Password
               ),
               r => { asyncResult = r; }
           );

            yield return current;

            // The callback is always called when the execution of the coroutine finishes

            // Exit if game session object could not be created
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // Obtain a game session object representing the login state
            session = asyncResult.Result;
        }

        // Get list of takeover information

        Debug.Log("Get list of takeover information");

        {
            AsyncResult<EzListTakeOverSettingsResult> asyncResult = null;

            var current = gs2.Account.ListTakeOverSettings(
                r => { asyncResult = r; },
                session,
                accountNamespaceName,
                30,
                null
            );

            yield return current;

            // callback is always called when the execution of the coroutine is finished

            // Callback notified when API call completes
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            List<EzTakeOver> items = asyncResult.Result.Items;
            foreach (var item in items)
            {
                // Information about the takeover is retrieved.
            }
        }

        // GS2 SDK termination process

        Debug.Log("GS2 SDK termination process");

        {
            // Call this when exiting a game, for example.
            // Calling it frequently is not expected.
            var current = profile.Finalize();

            yield return current;
        }
    }

    private void OnError(Exception e)
    {
        Debug.Log(e.ToString());
    }

    // Update is called once per frame
    void Update()
    {

    }
}
// *Replace (Project name) with the appropriate project name and execute.

// MyActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include <gs2/ez/Gs2Ez.hpp>
#include <memory>
#include "MyActor.generated.h"

UCLASS()
class (Project name) _API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // Sets default values for this actor's properties
    AMyActor();

    // Client ID issued by GS2-Identifier
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString ClientId;

    // Client Secret issued with GS2-Identifier
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString ClientSecret;

    // Namespace name of the GS2-Account for which the account is to be created
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString AccountNamespaceName;

    // the encryption key used to compute the signature to be placed on the account's authentication results
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString AccountEncryptionKeyId;

private:
    std::shared_ptr<gs2::ez::Profile> ProfilePtr;
    std::shared_ptr<gs2::ez::Client> ClientPtr;

    gs2::ez::GameSession GameSession;
    gs2::ez::account::EzAccount EzAccount;

    void ProfileInitialize();
    void AccountCreate();
    void ProfileLogin();
    void AccountListTakeOverSettings();
    void ProfileFinalize();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};
// MyActor.cpp

#include "MyActor.h"
#include "Engine.h"

// Sets default values
AMyActor::AMyActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    ProfileInitialize();
}

void AMyActor::ProfileInitialize()
{
    // Initialize GS2 SDK client

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.initialize");

    ProfilePtr = std::make_shared<gs2::ez::Profile>(
        TCHAR_TO_ANSI(*ClientId),
        TCHAR_TO_ANSI(*ClientSecret),
        gs2::ez::Gs2BasicReopener()
        );

    ClientPtr = std::make_shared<gs2::ez::Client>(
        *ProfilePtr
        );

    ProfilePtr->initialize(
        [this](gs2::ez::Profile::AsyncInitializeResult r)
        {
            if (r.getError())
            {
                // Exit if account could not be created
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.initialize failed.");
            }
            else
            {
                AccountCreate();
            }
        }
    );
}

void AMyActor::AccountCreate()
{
    // Create a new account

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "account.create");

    ClientPtr->account.create(
        [this](gs2::ez::account::AsyncEzCreateResult r)
        {
            if (r.getError())
            {
                // Exit if account could not be created
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.create failed.");
            }
            else
            {
                // Retrieve created account information
                EzAccount = r.getResult()->getItem();

                ProfileLogin();
            }
        },
        TCHAR_TO_ANSI(*AccountNamespaceName)
    );
}

void AMyActor::ProfileLogin()
{
    // Login

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.login");

    ProfilePtr->login(
        [this](gs2::ez::Profile::AsyncLoginResult r)
        {
            if (r.getError())
            {
                // Exit if game session object could not be created
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.login failed.");
            }
            else
            {
                // Get a game session object representing the login state
                GameSession = *r.getResult();

                AccountListTakeOverSettings();
            }
        },
        gs2::ez::Gs2AccountAuthenticator(
            ProfilePtr->getGs2Session(),
            TCHAR_TO_ANSI(*AccountNamespaceName),
            TCHAR_TO_ANSI(*AccountEncryptionKeyId),
            EzAccount.getUserId(),
            EzAccount.getPassword()
        )
    );
}

void AMyActor::AccountListTakeOverSettings()
{
    // Get a list of takeover information

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "account.listTakeOverSettings");

    ClientPtr->account.listTakeOverSettings(
        [this](gs2::ez::account::AsyncEzListTakeOverSettingsResult r)
        {
            if (r.getError())
            {
                // Exit if the list of transfer information could not be obtained
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.listTakeOverSettings failed.");
            }
            else
            {
                auto& items = r.getResult()->getItems();
                for (auto i = 0; i < items.getCount(); ++i)
                {
                    // Information about the transfer is retrieved.
                }

                ProfileFinalize();
            }
        },
        GameSession,
        TCHAR_TO_ANSI(*AccountNamespaceName)
    );
}

void AMyActor::ProfileFinalize()
{
    // GS2 SDK termination process

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.finalize");

    // Call this when exiting a game, for example.
    // Not intended to be called frequently.
    ProfilePtr->finalize(
        [this]()
        {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, "successfull.");
        }
    );
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

Implementation Sample Projects

You can get a sample implementation project that works with Unity.

GS2 Sample Project for Unity

This is a sample implementation of how the following functions are imagined to work in the game.

Download

GS2 SDK for Game Engine

Game Server Services provides SDKs that can be used by major game engines.
The SDK for game engines is provided in a higher-level API format than the regular SDK, with a focus on use from within the game.

GS2 SDK for Unity

This SDK is licensed under the Apache License 2.0.
You must clearly indicate somewhere in your program that you are using libraries provided under the Apache License 2.0.

This SDK includes LitJson (Gs2/Plugin/LitJSON.dll), which is in the public domain.
Since this dll is used for operations that are fundamental to the operation of GS2 SDK, it cannot be removed.

This SDK includes websocket-sharp(Gs2/Plugin/websocket-sharp.dll) which is MIT License.
The license that should be noted is as follows
https://raw.githubusercontent.com/sta/websocket-sharp/master/LICENSE.txt
This dll is used for operations that are fundamental to the operation of GS2 SDK and cannot be removed.

This SDK includes protobuf(Gs2/Plugin/Google.Protobuf.dll) which is BSD License.
The license that should be noted is as follows
https://github.com/protocolbuffers/protobuf/blob/master/LICENSE
This dll can be removed if GS2-Realtime is not used.

Installation Procedure

If you are using Unity 2019.3 or later

GS2 SDK for Unity Installer Version 2022.3.1

Start the Unity Editor and import the .unitypackage file from the Import Package menu.
Then select "Window > Game Server Services > SDK Installer" from the Unity Editor menu and follow the wizard's instructions.
If the installation does not work properly after installation is complete, try restarting the Unity Editor once.

If you are using Unity 2019.2 or earlier

GS2 SDK for Unity consists of GS2-CSharp-SDK and GS2 SDK for Unity.

GS2-CSharp-SDK GitHub

Select "Code > Download Zip" on this page and place the downloaded source code in your project.
(Unity Project)/Assets/Scripts/Runtime/Sdk/Gs2

GS2 SDK for Unity GitHub

Select "Code > Download Zip" on this page and place the downloaded source code in your project.
(Unity Project)/Assets/Scripts/Runtime/Sdk/Gs2/Unity

Unity Release Note 2019.3.0
Package Manager: Fixed an issue where using some npm registry backends as scoped registries would fail with an error like com.foo.bar: Cannot read property '0.0.1' of undefined. (1177614)

Implementation Notes

When building for Windows, change the BuildSettings from x86 to x86_64. x86 will give an error.

GS2 SDK for Unreal Engine 4

The SDK itself is licensed under the Apache License 2.0.
You must clearly indicate somewhere in your program that you are using libraries provided under the Apache License 2.0.

This SDK includes the following software customized by Game Server Services, Inc.

Since these are used for operations that are fundamental to the operation of the SDK, they cannot be removed.
The license for the portions of these software modified by Game Server Service, Inc. is provided under the Apache License 2.0 in accordance with the terms of the respective software.
All other portions are subject to the license of the respective software.
Both licenses require that the full text of each software copyright notice and license be included in each copy of the software to be distributed.

Download

GS2 SDK for Unreal Engine 4 Version 2021.7.3

Installation Procedure

Extract the SDK download package and make the following changes to your Unreal Engine 4 project

  1. Copy the gs2-unreal-engine-sdk/gs2 directory to any location under Source/(project name).
  2. Make the following changes to (project name).Build.cs
    • Add "HTTP" and "WebSockets" to PublicDependencyModuleNames.
      • Example: PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HTTP", "WebSockets" });
    • Add to PublicSystemIncludePaths the location of the gs2 directory of the GS2 SDK for Unreal Engine 4.
      • Example: PublicSystemIncludePaths.Add(System.IO.Path.Combine(ModuleDirectory, "gs2-unreal-engine-sdk/"));
  3. Regenerate the Visual Studio project from the context menu of (project name).uproject.
If you are using iOS build

As of Unreal Engine 4.26, there is a problem in iOS builds where the engine's root CA certificate is not loaded correctly and will fail to connect to the GS2 server.

  1. Copy Engine/Content/Certificates/ThirdParty/cacert.pem of the engine to Content/Certificates/cacert.pem of the project
  2. In the Project Settings, under Advanced Settings for Packaging, Add Certificates in the "Additional Non-Assets Directories to Copy" field.

The above settings do not need to be changed even when targeting devices other than iOS.

Implementation Notes

GS2 SDK

The SDK itself is licensed under the Apache License 2.0.
You must clearly indicate somewhere in your program that you are using libraries provided under the Apache License 2.0.

GS2-Java-SDK

https://github.com/gs2io/gs2-java-sdk

GS2-PHP-SDK

https://github.com/gs2io/gs2-php-sdk

GS2-Golang-SDK

https://github.com/gs2io/gs2-golang-sdk

GS2-Python-SDK

https://github.com/gs2io/gs2-python-sdk

GS2-Typescript-SDK

https://github.com/gs2io/gs2-typescript-sdk

GS2-CSharp-SDK

https://github.com/gs2io/gs2-csharp-sdk

Changelog

GS2-Insight

GS2-Insight GitHub

Added

GS2 SDK for Unity / GS2 C# SDK

[2022.3.4] - 2022-03-10

Changed

Implementation Example: var notification = JoinNotification.FromJson(JsonMapper.ToObject(message.payload));

Guide

GS2-Identifier Guide

What is GS2-Identifier?

Manage credentials (authentication information) and access privileges to access GS2 services
GS2-Identifier is the mechanism.

Authority management of whether each service can be accessed is performed for each GS2-Identifier user ( hereinafter referred to as " user ").

The definition of what GS2 services are available to users (Security Policy) Assign a

GS2 authenticates the accessing user using credentials and returns a project token.
The game app/management tool uses this project token to access each service.

Detailed permission settings are defined in the security policy, which is assigned to each user.

user

The following is an overview of the data structures that users have

Security Policy

The following policies are pre-defined in the security policy

Security Policy Name Description
AdministratorAccess Authorization to use all APIs
ApplicationAccess Authority to call only APIs that do not lead to cheating
DeliveryAccess Authorization required for GS2-Distributor to perform resource overflow processing
UnauthenticatedAccess Authority to perform version checking (GS2-Version) only

The AdministratorAccess policy is a permission to access all GS2 services.

The ApplicationAccess policy that is assumed to be embedded and used within the game app is
It is configured to prevent calls to APIs that can manipulate the server in ways that could lead to cheating.

Security Policy Format

Security policies are described in JSON format.

In the "Statements" section, we have "Effects", "Actions", "Resources Include each of the elements in the "Elements" section.
The * (asterisk) represents a wildcard.

The simplest security policy would be as shown in the example.
This security policy is designed to ensure that any operation can be performed on any service, any API.

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

“Actions”

The security policy in the example is that any operation can be performed on the GS2-Inbox service.
The privileges of a user assigned this security policy do not allow access to any services other than GS2-Inbox.

The * (asterisk) represents a wildcard.

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

Enumeration of actions

"Actions" contains a list of actions, methods that can and cannot be accessed and executed.
The list can be expanded.
Specify the methods listed in the reference for each service.

Put a :(colon) in between, like [service name]:[method name].

The service name can be specified as
Gs2Inbox
The name of each service should be a series of Gs2 without the - (hyphen), like "Gs2".

The method name is
SendMessage
with the first letter capitalized (upper camel case).

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

“Effect”

Specify whether access to the API is allowed or not in this policy.

Designation Access
Allow permit
Deny not permitting

“Resources”

This variable will specify the range of resources affected by this policy.
Currently, only *(asterisk) can be specified.

GS2-Deploy Template Format

This is the format specification for the template file used when creating a stack with GS2-Deploy.
It can be written in JSON or YAML format.

Types of sections

A template consists of the following sections

Example of Resource Creation with GS2-Deploy Template (YAML)

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2-Account initialize template Version 2021-12-03

Globals:
  Alias:
    AccountNamespaceName: game-0001
    KeyNamespaceAccountAuthentication: account-encryption-key-namespace
    KeyAccountAuthentication: account-encryption-key
    GatewayNamespaceName: gateway-0001

Resources:
  GatewayNamespace:
    Type: GS2::Gateway::Namespace
    Properties:
      Name: ${GatewayNamespaceName}

  KeyNamespaceAccountAuthentication:
    Type: GS2::Key::Namespace
    Properties:
      Name: ${KeyNamespaceAccountAuthentication}

  KeyAccountAuthentication:
    Type: GS2::Key::Key
    Properties:
      NamespaceName: ${KeyNamespaceAccountAuthentication}
      Name: ${KeyAccountAuthentication}
    DependsOn:
      - KeyNamespaceAccountAuthentication

  AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: ${AccountNamespaceName}

Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
  KeyAccountAuthenticationKeyId: !GetAttr KeyAccountAuthentication.Item.KeyId
  GatewayNamespaceName: !GetAttr GatewayNamespace.Item.Name
Section Required Description
GS2TemplateFormatVersion Specifies the template format. Currently only 2019-05-01 can be defined.
Description You can enter a description or other information about the template.
Globals This section is for defining Alias attributes (specifying string substitutions).
Resources Define resources for each GS2 service to be included in the stack.
Outputs Define output values to be displayed in the management console.

Globals section

Alias Attribute

Replaces strings in the Resources and Outputs sections with the specified string.
Replace the string on the left side with ${...} The part enclosed by ${} is replaced by the string on the right side, as in the following example.

Example of Alias attribute definition (YAML)

Globals:
  Alias:
    AccountNamespaceName: game-0001

Example of replacement specification: ${AccountNamespaceName}

Resources section

Defines the resource to be generated, with Type and Properties attributes, and DependsOn attribute if necessary.

Resources section (YAML)

Resources:
  KeyNamespaceAccountAuthentication: # Name of resource definition
    Type: GS2::Key::Namespace # Specify resource
    Properties:
      Name: ${KeyNamespaceAccountAuthentication}

  KeyAccountAuthentication: # Name of resource definition
    Type: GS2::Key::Key # Specify resource
    Properties:
      NamespaceName: ${KeyNamespaceAccountAuthentication}
      Name: ${KeyAccountAuthentication}
    DependsOn: # Specify name of dependent resource definition
      - KeyNamespaceAccountAuthentication # Dependent on KeyNamespaceAccountAuthentication creation

  AccountNamespace: # Name of the resource definition
    Type: GS2::Account::Namespace # Specify resource
    Properties:
      Name: ${AccountNamespaceName}

Type attribute

Specification of resources to be generated for the service.
Specify the entity name in the GS2-Deploy reference page for each service.

 Example: Type: GS2::Account::Namespace.

Properties attribute

Specify the value to be given to the property value when the resource is created.

DependsOn attribute

Specifies the name of the dependent resource so that the resource will be created following other resources.

Outputs section

Define output values to be displayed in the management console.

Outputs section (YAML)

Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
  KeyAccountAuthenticationKeyId: !GetAttr KeyAccountAuthentication.Item.KeyId
  GatewayNamespaceName: !GetAttr GatewayNamespace.Item.Name

!GetAttr tag

The !GetAttr tag can be used to obtain the property values of the generated results for each resource.

Example of !GetAttr tag usage (YAML)

AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: ${AccountNamespaceName}
Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name

In this example, GS2::Account::Namespace is specified in AccountNamespace, so ,
The Namespace is generated by GS2-Account.
The result is retrieved in AccountNamespace and stored in AccountNamespace.Item with NameSpace model.
You can get the namespace name with !GetAttr AccountNamespace.Item.Name.

In addition, the following are assigned to the !GetAttr tag as reserved words, and their values can be retrieved.

Type Description
Gs2::Region string Region type
Gs2::OwnerId string Owner ID

!Join tag

The !Join tag concatenates the strings in the following array. A delimiter (delimiter) can be specified.

 Format: !Join [ specify delimiter, [list of strings to concatenate]]

Example usage of !Join tag, !GetAttr Gs2::Region, and !GetAttr Gs2::OwnerId (YAML)

  QueueNamespace:
    Type: GS2::JobQueue::Namespace
    Properties:
      Name: ${QueueNamespaceName}
      PushNotification:
        GatewayNamespaceId: !Join
          - ':'
          - - 'grn'
            - 'gs2'
            - !GetAttr Gs2::Region
            - !GetAttr Gs2::OwnerId
            - 'gateway'
            - ${GatewayNamespaceName}

The usage example shows string generation of GRN (GS2 Resource Name).

Master Data Management

Definition of Terms

terminology meaning
model master Data that does not change for each game player updated from the management screen.
model Data that does not change for each game player used from within the game
property Different data for each game player created based on the model

elements of the game, such as the parameters of the items you possess and the data that make up your quests.
Some data does not change from one game player to another.
Such data is called a model in GS2.
The data that is transformed from the model into data possessed by the game player is called properties.

General master data corresponds to models in GS2, and the concept of model master exists in GS2.
The difference between a model and a model master is that the data content is the same, but the difference is whether or not the data is actually in a state to be accessed by the game.

The data that can be edited on the GS2 administration screen is the model master, which changes to a model when it is converted to a state that can actually be used in the game.
The reason this conversion process is necessary is to ensure that all changes to the model master are reflected in the game at once.
Without this process, data in the process of updating data in the management screen would be reflected in the game.

Creation of master data

Example of master data management in GS2-Deploy template (YAML)

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 master data template Version 2010-06-26

Globals:
  Alias:
    NamespaceName: inventory

Resources:
  Namespace:
    Type: GS2::Inventory::Namespace
    Properties:
      Name: ${NamespaceName}

  NamespaceSettings:
    Type: GS2::Inventory::CurrentItemModelMaster
    Properties:
      NamespaceName: ${NamespaceName}
      Settings:  # The data from here down is originally to be specified in JSON, but it can be written as yaml and reflected.
        version: 2019-02-05
        inventoryModels:
          - name: item
            metadata: ITEM
            initialCapacity: 40
            maxCapacity: 60
            itemModels:
              - name: item-0001
                metadata: ITEM_0001
                maxCount: 99
                sortValue: 1
              - name: item-0002
                metadata: ITEM_0002
                maxCount: 99
                sortValue: 2
              - name: item-0003
                metadata: ITEM_0003
                maxCount: 99
                sortValue: 3
          - name: character
            metadata: CHARACTER
            initialCapacity: 30
            maxCapacity: 50
            itemModels:
             - name: character-0001
               metadata: CHARACTER_0001
               maxCount: 1
               sortValue: 1

    DependsOn:
      - Namespace

This conversion process exports all model masters to JSON format files and uploads the JSON files to reflect them as a batch model.
You can use the GS2 administration screen to manipulate model masters and export them to JSON format files, or you can create Excel or your own administration tool to reflect data in models without registering any model masters in GS2.

Master data can also be managed within GS2-Deploy templates. In this case, it will be easier to use version control tools such as git, so please consider this option as well.

Manage master data in an operationally convenient manner.

GS2 Service Extension

Example of using GS2-Script to assign items to GS2-Inventory (Lua)

-- Get model information from argument
namespace_name = args['namespaceName']
user_id = args['userId']
inventory_name = args['inventoryName']
item_name = args['itemName']
acquire_count = args['acquireCount']
expires_at = args['expiresAt']

inventory_client = gs2('inventory')

-- issue a request
result = inventory_client.acquire_item_set_by_user_id({
    namespace_name=namespace_name,
    user_id=user_id,
    inventory_name=inventory_name,
    item_name=item_name,
    acquire_count=acquire_count,
    expires_at=expires_at,
})

-- Respond to the response
if(result['isError']) then
    fail(result['statusCode'], result['errorMessage'])
end

result = result['result']

GS2 is designed so that a gaming system can be built with standard features for general use.
However, depending on the use cases in a game, there may be things that cannot be achieved with the standard GS2 functions.

GS2 supports script extensions in Lua to handle such cases.
With GS2-Account, when creating a new account When authenticating an account When registering transfer settings
Scripts registered in GS2-Script can be executed at such times as when a handover is executed.
This allows us to meet the need to deliver rewards to the gift box when the transfer is set up.
The following is a list of the most common problems that can be encountered when using this system.
Registering to take over multiple times and receiving rewards as many times as you want would break the game system.
If you want to be able to grant it only once, you can implement it in combination with the frequency limit functionality provided by GS2-Limit, for example.
Please be creative in your scripts.

Stamp Sheet Overview

GS2 has a system called "Stamp Sheet" that allows processing to be performed in coordination with other services within GS2.
The use of stamp sheets is expected to become an integral part of using GS2.
You may read this section now or refer to it when you actually use the stamp sheet.

For example, GS2-Money, which handles the currency charged, and GS2-Inventory, which handles the in-game possessions, can be combined to create a
The process of purchasing items with the charged currency can be realized on a stamp sheet.
If you send a separate request to GS2-Money to spend the currency and a separate request to GS2-Inventory to retrieve the item, the
If the application is stopped in the middle of processing or due to cheating, only one of the requests may be processed.

Stamp sheets, on the other hand, are used for consumption actions (in this case, the consumption of billable currency) and
The acquisition action (in this case, the acquisition of an item) is combined into a single action.
In this example, the item is purchased with the charged currency, so the product is registered in the product master of GS2-Showcase, which realizes the product in the game.
Register a stamp sheet to be issued upon purchase for this item.
For more information on GS2-Showcase and the Product Master, please visit the GS2-Showcase page for more information.

Once the stamp sheet has been registered with GS2-Showcase, the next step is to obtain and execute the stamp sheet on the client.
In GS2-Showcase, a stamp sheet can be obtained with the method Buy.
The next step is to execute the obtained stamp sheet, which will process the consumption of the charged currency and the acquisition of the item.

Here is an example of purchasing an item, but you can also use GS2-Quest to purchase other items.
Spending stamina to acquire items to complete quests, and so on.
There are many possible situations in which stamp sheets can be used.

It is also possible to set up multiple consume and obtain actions on a single stamp sheet.
However, if multiple acquisition actions are set, they must be processed in conjunction with GS2-JobQueue.
This means that if the server that manages the reward is down when the reward is granted, the chain of related services
The reason for this is to avoid unavailability of the system.
For such cases, the reward process is registered in GS2-JobQueue when the stamp sheet is executed, and the
The system provides a mechanism to retry even if the execution of the reward process fails once.
For more information, see GS2-JobQueue page for more information.

Stamp Sheet page has a more detailed description and list of consumed and obtained actions.

Sample code to execute a stamp sheet (Unity)

Sample code to execute a stamp sheet (Unity)


    // Prepare to use UnityEvent<Gs2Exception> type
    [System.Serializable]
    public class OnErrorCallback : UnityEngine.Events.UnityEvent<Gs2Exception>
    {
    }

    // Define behavior in case of stamp sheet execution error
    private void OnError(Exception e)
    {
        Debug.Log(e.ToString());
    }

    private IEnumerator StampSheetTest()
    {
        var machine = new StampSheetStateMachine(stampSheet, client, distributorNamespeceName, stampSheetEncryptKeyId);
        UnityEvent<Gs2Exception> m_events = new OnErrorCallback();
        m_events.AddListener(OnError);
        yield return machine.Execute(m_events);
    }

Example of registering a method to be run when stamp sheet execution is complete (Unity)

    machine.OnCompleteStampSheet.AddListener(Machine_OnCompleteStampSheet); // register before executing machine.Execute

    private void Machine_OnCompleteStampSheet(EzStampSheet sheet, Gs2.Unity.Gs2Distributor.Result.EzRunStampSheetResult result)
    {
     // Write process when stamp sheet execution is completed
    }

First, a stamp sheet state machine is created with four arguments.

Next, Execute with the stamp sheet state machine.
The argument of Execute must be a UnityEvent type to be registered for error handling.

The stamp sheet state machine can also register methods and callbacks to run when stamp sheet execution is complete.
Before executing Execute, add a callback as shown in the second sample code.
This way, after Execute is executed, the respective callbacks will be executed on error and on success.

GS2 UIKit for Unity

GS2 UIKit for Unity is intended to enable implementation of GS2 functionality on Unity's UI without writing code.
This section summarizes how to create a UI using UIKit for Unity.

How to Install

GS2 SDK for Unity must be installed to use this SDK.
This SDK is licensed under the Apache License 2.0.

If you are using Unity 2019.3 or later

GS2 SDK for Unity Installer Version 2022.3.1

Start the Unity Editor and import the .unitypackage file from the Import Package menu.
Then select "Window > Game Server Services > UIKit for Unity Installer" from the Unity Editor menu and follow the wizard's instructions.
If the installation does not work properly after installation is complete, try restarting the Unity Editor once.

If you are using Unity 2019.2 or earlier

GS2 UIKit for Unity GitHub

Select Clone or Download and place the downloaded source code in the project.

Process Flow

The rough process flow at each prefab is as follows

  1. Fetcher component to get information from GS2 services
  2. Reflected in UI with View component
  3. Active control by conditions in the View/Enabler component
  4. Execution of various actions by Action component by pressing buttons, etc.

GS2 UIkit for Unity Reference

Prefabrication/component references for each service are listed below.

GS2 UIkit for Unity Sample

GS2 UIKit for Unity functionality implementation sample.

How to Install

GS2 UIKit Sample Version 2022.4.1

Download the above gs2-uikit-sample_2022.4.1.unitypackage file.
Start Unity Hub and create a new project for the sample deployment.
Alternatively, start the Unity Editor and create a new project.
Import the above unitypackage file from the Import Package in the Assets menu of the Unity Editor.

Preparation for startup

Prepare to run the sample.
As an example, this section covers the steps to run a sample that displays experience values in GS2-Experience.

Open a sample scene in Unity

In the project from which you imported the sample, open the scene.
Here we open the file Experience.unity as an example.

Experience Sample Scenes:
(Unity Project)/Assets/Game Server Services/Samples/UIKit/Gs2Experience/Scenes/Account.unity.

Credential Settings

Configure credentials (authentication information) for client access to GS2.
Create a project in the Management Console.
Create a stack with the following template file in GS2-Deploy's Create a new stack in the Management Console.

The path of the template for which you want to set the credential:
(Unity project)/Assets/Game Server Services/Samples/UIKit/Core/Settings/initialize_credential_template.yaml

Set the ApplicationClientId and ApplicationClientSecret values of the stack output to the following SampleEnvironment.asset.

(Unity project)/Assets/Game Server Services/Samples/UIKit/Core/Settings/SampleEnvironment.asset

Field Name terms
Name Project Name
Region region
Client Id ClientId of credential
Client Secret ClientSecret for credential

Deproy Template Settings

Prepare the resources necessary for the sample to work.
Create a stack with the following template file in Create New Stack of GS2-Deploy in the Management Console.
Set the stack name to Experience as an example, the description to any text, select the file in Template Data, and upload the template.

Path to the template for setting the experience:.
(Unity project)/Assets/Game Server Services/Samples/UIKit/Gs2Experience/Settings/initialize_experience_template.yaml

The configuration is complete when the Execution state becomes Create Complete.

Explanation of each sample

Service Overview & Pricing

GS2-Account

Service Overview

This service provides account management functions to identify users.

The service supports data transfer using email addresses + passwords and social accounts to enable data transfer when changing device models.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Regarding transfer information, the registration, updating, and deletion of the same user's information should be limited to three times per second.
This limit does not apply to different users.

Basic usage

Games that implement network functionality require account management functionality.
Without the ability to identify individuals, many elements of network functionality, such as managing personal belongings and friends, cannot be realized.

For account management, GS2 offers two types of implementation methods.

Account Management Structure

GS2 provides a service called GS2-Account to realize account management functions.

anonymous account

New issue of anonymous account Example implementation (Unity/UniTask enabled)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace1" // namespace name
);
var result = await domain.CreateAsync();
ModelAsync(); var item = await result;

Debug.Log(Item.AccountId); // game player account
Debug.Log(Item.UserId); // account ID
Debug.Log(Item.Password); // Password
Debug.Log(Item.TimeOffset); // Correction value for the current time (seconds from the current time)
Debug.Log(Item.CreatedAt); // Creation date and time

Issue new anonymous account Implementation example (Unity)

AsyncResult<EzCreateResult> asyncResult = null;
var current = gs2.Account.Create(
    callback: r => { asyncResult = r; }
    namespaceName: "namespace1" // namespace name
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var item = result.Item;

Debug.Log(Item.AccountId); // game player account
Debug.Log(Item.UserId); // account ID
Debug.Log(Item.Password); // password
Debug.Log(Item.TimeOffset); // Correction value for the current time (seconds from the current time)
Debug.Log(Item.CreatedAt); // Creation date and time

When you start a game for the first time, GS2-Account will issue you an account in a category called Anonymous Accounts.
Anonymous accounts are accounts that can be used to identify the user, but do not have any information that identifies who the game player is.

The reason why we issue such accounts is that when you start a game for the first time, you need to register your e-mail address, etc.
This is because making it mandatory will increase the withdrawal rate from the game.
Therefore, as a sufficient factor to identify the user, GS2-Account issues a random ID and password when the API for creating a new account is called.
The accessing client stores the issued ID and password in its local storage and uses that information for the login process.

takeover settings

Example of implementation (Unity/UniTask enabled)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).TakeOver(
    type: 0 // slot number
);
var result = await domain.AddTakeOverSettingAsync(
    userIdentifier: "user-0001@gs2.io", // user ID for takeover
    password: "password-0001" // password
);
var item = await result.ModelAsync();

Debug.Log(Item.TakeOverId); // takeover setting
Debug.Log(Item.UserId); // User ID
Debug.Log(Item.Type); // slot number
Debug.Log(Item.UserIdentifier); // User ID for transfer
Debug.Log(Item.Password); // Password
Debug.Log(Item.CreatedAt); // Creation date and time

Registration of Takeover Settings Implementation Example (Unity)

AsyncResult<EzAddTakeOverSettingResult> asyncResult = null;
var current = gs2.Account.AddTakeOverSetting(
    callback: r => { asyncResult = r; }
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    type: 0, // slot number
    userIdentifier: "user-0001@gs2.io", // User ID for takeover
    password: "password-0001" // password
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var item = result.Item;

Debug.Log(Item.TakeOverId); // takeover setting
Debug.Log(Item.UserId); // User ID
Debug.Log(Item.Type); // slot number
Debug.Log(Item.UserIdentifier); // User ID for transfer
Debug.Log(Item.Password); // Password
Debug.Log(Item.CreatedAt); // Creation date and time

Implementation example of takeover execution (Unity/UniTask enabled)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace1" // namespace name
);
var result = await domain.DoTakeOverAsync(
    type: 0, // slot number
    userIdentifier: "user-0001@gs2.io", // user ID for takeover
    password: "password-0001" // password
);
var item = await result.ModelAsync();

Debug.Log(r.Result.Item.AccountId); // game player account
Debug.Log(r.Result.Item.UserId); // account ID
Debug.Log(r.Result.Item.Password); // password
Debug.Log(r.Result.Item.TimeOffset); // Correction value for the current time (seconds starting from the current time)
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time

Implementation example of takeover execution (Unity)

AsyncResult<EzDoTakeOverResult> asyncResult = null;
var current = gs2.Account.DoTakeOver(
    callback: r => { asyncResult = r; }
    namespaceName: "namespace1", // namespace name
    type: 0, // slot number
    userIdentifier: "user-0001@gs2.io", // user ID for takeover
    password: "password-0001" // password
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var item = result.Item;

Debug.Log(r.Result.Item.AccountId); // game player account
Debug.Log(r.Result.Item.UserId); // account ID
Debug.Log(r.Result.Item.Password); // password
Debug.Log(r.Result.Item.TimeOffset); // Correction value for the current time (seconds starting from the current time)
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time

Anonymous accounts have the advantage of not requiring a registration sequence, but of course there are disadvantages.
That is, the game players themselves do not know their own user IDs and passwords.

Therefore, GS2-Account provides a feature called "takeover settings.
The transfer settings are used to represent anonymous accounts as IDs/passwords that are more easily recognizable by game players.
Multiple transfer settings can be made for a single anonymous account.

For example, slot 1 can be set to an email address and an optional password, and slot 2 can be set to an email address and an optional password.
Slot 2 is for registering information such as social networking account names.
Then, when you change the device model or want to log in to the same account on a different device, you can use
By entering the ID/password information registered in the transfer settings, login information for anonymous accounts can be obtained again.

I want to stop logging in from different devices.

Example of not allowing simultaneous logins on GS2-Gateway (Unity/UniTask enabled)

var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).WebSocketSession(
);
var result = await domain.SetUserIdAsync(
    allowConcurrentAccess: null
);
var item = await result.ModelAsync();

Debug.Log(r.Result.Item.ConnectionId); // connection ID
Debug.Log(r.Result.Item.OwnerId); // Owner ID
Debug.Log(r.Result.Item.NamespaceName); // namespace name
Debug.Log(r.Result.Item.UserId); // user ID
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time
Debug.Log(r.Result.Item.UpdatedAt); // Last updated

Example of not allowing simultaneous logins on GS2-Gateway (Unity)

AsyncResult<EzSetUserIdResult> asyncResult = null;
var current = gs2.Gateway.SetUserId(
    callback: r => { asyncResult = r; }
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    allowConcurrentAccess: null // allow connections from different clients at the same time?
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var item = result.Item;

Debug.Log(r.Result.Item.ConnectionId); // connection ID
Debug.Log(r.Result.Item.OwnerId); // Owner ID
Debug.Log(r.Result.Item.NamespaceName); // namespace name
Debug.Log(r.Result.Item.UserId); // user ID
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time
Debug.Log(r.Result.Item.UpdatedAt); // Last updated

When GS2-Account performs a transfer, the anonymous account information stored on the device to be transferred is
The password can be changed.
This feature can be used to disable login from the device from which you are transferring.

However, this method is not sufficient if you want to restrict login by multiple devices more strictly.
For example, it is possible to create a situation where several different devices have the same ID/password by, for example, performing data transfer between devices.
To handle such cases, please use the GS2-Gateway 's function to restrict double login.

The GS2-Gateway uses WebSockets to connect to GS2' s servers, and to receive events that occur on the servers, such as
For example, "I received a friend request," "A new present arrived in my gift box
The system is used to receive notifications such as "Matchmaking completed.

Due to the nature of this function, it is necessary to link a logged-in user ID to the WebSocket communication session.
When performing this association, it is possible to "disallow the connection if the corresponding user ID is already logged in".

Log in with the account information you created

Example implementation of getting signed account information with GS2-Account (Unity/UniTask enabled)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace1" // namespace name
).Account(
    userId: "user-0001" // account ID
);
var result = await domain.AuthenticationAsync(
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001", // GRN of the encryption key used to encrypt the authentication token
    password: "password-0001" // password
);
var item = await result.ModelAsync();
var body = result.Body;
var signature = result.Signature;

Debug.Log(r.Result.Item.AccountId); // game player account
Debug.Log(r.Result.Item.UserId); // account ID
Debug.Log(r.Result.Item.Password); // password
Debug.Log(r.Result.Item.TimeOffset); // Correction value for the current time (seconds starting from the current time)
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time
Debug.Log(r.Result.Body); // Account information to be signed
Debug.Log(r.Result.Signature); // Signature

Example implementation of getting signed account information with GS2-Account (Unity)

AsyncResult<EzAuthenticationResult> asyncResult = null;
var current = gs2.Account.Authentication(
    callback: r => { asyncResult = r; }
    namespaceName: "namespace1", // namespace name
    userId: "user-0001", // account ID
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001", // GRN of the encryption key used to encrypt the authentication token
    password: "password-0001" // password
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var item = result.Item;
Item; var body = result.Body;
Result; var signature = result.Signature;

Debug.Log(r.Result.Item.AccountId); // game player account
Debug.Log(r.Result.Item.UserId); // account ID
Debug.Log(r.Result.Item.Password); // password
Debug.Log(r.Result.Item.TimeOffset); // Correction value for the current time (seconds starting from the current time)
Debug.Log(r.Result.Item.CreatedAt); // Creation date and time
Debug.Log(r.Result.Body); // Account information to be signed
Debug.Log(r.Result.Signature); // Signature

Example implementation of obtaining an access token from signed account information with GS2-Auth (Unity)

AsyncResult<EzLoginBySignatureResult> asyncResult = null;
var current = gs2.Auth.LoginBySignature(
    callback: r => { asyncResult = r; }
    userId: "user-0001", // user ID
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001", // GRN of the encryption key used to create the signature
    body: "body", // Account credentials to be signed
    signature: "signature" // signature
);

yield return current;
if (asyncResult.Error ! = null)
{
    OnError(asyncResult.Error);
    OnError(asyncResult.Error); yield break;
}

var result = asyncResult;
var token = result.Token;
Token; var userId = result.UserId;
var expire = result.Expire;

Debug.Log(r.Result.Token); // access token
Debug.Log(r.Result.UserId); // user ID
Debug.Log(r.Result.Expire); // Expiration date

The GS2-Account login process is implemented in two steps.

  1. Send anonymous account user ID/password to GS2-Account and receive response with signed account information if password verification passes
  2. Send signed account information to GS2-Auth and issue an access token for the user ID if it passes signature verification

GS2-Profile::Login combines these two steps into one.
This is explained in Getting Started => How to Implement Account Management Functions.

Access token expiration date

Access tokens have an expiration date.
Therefore, it is not recommended to use acquired access tokens on a permanent basis.

The expiration date of the access token is included in the return value when the access token is obtained.
The process of acquiring an access token must be performed again before the expiration date expires.

GS2-Auth

Service Overview

GS2-Auth is a service that issues "access tokens" to identify game players within GS2.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

GS2-Chat

Service Overview

Provides text-based chat functionality.

Message data is managed on a room-by-room basis and logs are maintained for the past 24 hours.
Rooms can be assigned a password, and if so, passwords are required to retrieve messages and post requests.
Rooms can be assigned a user ID whitelist, which means that only game players on the whitelist will be able to retrieve and post messages.

Messages can be categorized, allowing the client to toggle how the payload is parsed.
For example, for category 0 the text is included in the payload as is. Category 1includes the ID of the stamp in the payload. You can usecategory 1` in this way.

If you subscribe to a room, you will receive push notifications from the server when new posts are made to the room.
At this time, you can set the categories in which you would like to receive notifications. By dividing the categories by message type and importance, you can improve the user experience by allowing game players to set the types of messages for which they would like to receive notifications.
There is also a setting in the subscription settings to forward to mobile push notifications, so make good use of it.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

You may only post up to three times per second per room.
Please avoid implementing an extremely large number of people who can participate in one room, or encouraging people to post all at once.
The maximum number of subscribers to a room is 1000.

GS2-Datastore

Service Overview

Provides the ability to store arbitrary binary data on the server.
Uploaded data is subject to access permission control (ACL - Access Control List).

The data can be stored in a public directory, where anyone can access the data, or in a
protected, accessible only to game players with the specified user ID Three types of ACLs can be set:private`, which allows access only to the user.

Uploaded data is automatically backed up and can be restored within 30 days even if the data is updated or deleted.
Uploaded data is assigned a unique ID (UUID v4) and generation ID, and the generation ID is updated when data is updated or deleted.
When downloading data, the generation ID is specified to identify the specific file.

The generation ID can be included in the download request to avoid unintentionally retrieving a newer version of the data if another player attempts to access the data at the same time as the data is being updated.
By adding the generation ID to the download request, you can ensure that you are downloading the data as of the time you list it.

However, some games may not want to have access to older generation data forever.
Therefore, an option exists to allow downloading of older generation data only within 60 minutes of the update and only for one previous generation, except for the owner of the data.

Please consider your tolerance for cheating when using this feature to manage your saved data.
Other GS2 services are controlled so that addition and subtraction cannot be freely performed according to game specifications.
However, trusting local save data can be a source of cheating.
If GS2 functionality is provided, use that in preference, and only control elements that have only minor impact if tampered with, such as the exchange of UGC content or configuration settings.

Pricing

General usage

0.02 yen per API request

Service-specific

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

Some games may want to share UGC, user-generated content (ghost data for racing games or stage edit data) with other players.
This datastore function can be used in such cases.

access authorizations

The data store can upload any binary data to the server.
Access permissions can be set for uploaded data.
There are several policies for access privileges, which can be set for each piece of data.

public

This is used when you want to attach ghost data to ranking scores.
By storing the ID of the ghost data as metadata of the score, you can design the system so that when the ranking is retrieved, the ghosts of races that achieved that score can be retrieved from the data store.

protect

Information that you want to make available only to specific parties. For example, "I want to upload a photo to a chat room and grant access only to the participants of the room.

private

This can be used when you want to achieve features such as cloud saving.

Upload Data

Uploading data consists of three steps.

The reason for the three steps is that GS2-Datastore provides management functions for storing and loading binary data on the server, but it does not provide the ability to store and load binary data on the server.
This is because the binary data is actually stored on a file server, not on GS2.
Therefore, the
1. Obtain a URL for uploading management information such as the name of the data and access rights to the file server in a request to GS2, and
1. Uploading data to the obtained URL with an HTTP client, and
1. Report to GS2 that the upload has been successfully completed.
The three steps are as follows.

Get URL for upload

Before uploading a file, the URL for uploading is obtained based on management information such as data name and access rights.
The URL obtained here will be uploaded as a PUT request by the HTTP client.

Implementation example
Get URL for upload (Unity/UniTask enabled)

var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var result = await domain.PrepareUploadAsync(
    name: "dataObject-0001", // name of data
    scope: "public", // file access rights
    allowUserIds: null, // list of user IDs to be published
    updateIfExists: null // if data already exists, raise an error or update the data
);
var item = await result.ModelAsync();
var uploadUrl = result.UploadUrl;

Debug.Log(item.DataObjectId); // data object
Debug.Log(item.Name); // Name of data
Debug.Log(item.UserId); // user ID
Debug.Log(item.Scope); // File access rights
Debug.Log(item.AllowUserIds); // User ID list to be published
Debug.Log(item.Status); // status
Debug.Log(item.Generation); // Data generation
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated date
Debug.Log(uploadUrl); // URL used to perform the upload process

Get URL for upload Implementation example (Unity)

AsyncResult<EzPrepareUploadResult> asyncResult = null;
var current = gs2.Datastore.PrepareUpload(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    scope: "public", // file access rights
    name: "dataObject-0001", // name of data
    allowUserIds: null, // User ID list to be published
    updateIfExists: null // if data already exists, raise an error or update the data
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var uploadUrl = result.UploadUrl;

Debug.Log(item.DataObjectId); // data object
Debug.Log(item.Name); // Name of data
Debug.Log(item.UserId); // user ID
Debug.Log(item.Scope); // File access rights
Debug.Log(item.AllowUserIds); // User ID list to be published
Debug.Log(item.Status); // status
Debug.Log(item.Generation); // Data generation
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated date
Debug.Log(uploadUrl); // URL used to perform the upload process

Upload data

Upload to the obtained URL.
Upload is performed using a PUT request with an HTTP client to the file server, not to GS2.

Report completion of upload

Reports the successful completion of the upload.
With this report, GS2 can return the URL where the latest data was placed the next time the URL for downloading is obtained.

Implementation example
Reporting completion of upload (Unity/UniTask enabled)

var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).DataObject(
    dataObjectName: "dataObject-0001" // Name of the data
);
var result = await domain.DoneUploadAsync(
);
var item = await result.ModelAsync();

Debug.Log(item.DataObjectId); // data object
Debug.Log(item.Name); // Name of data
Debug.Log(item.UserId); // user ID
Debug.Log(item.Scope); // File access rights
Debug.Log(item.AllowUserIds); // User ID list to be published
Debug.Log(item.Status); // status
Debug.Log(item.Generation); // Data generation
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated date

Report completion of upload (Unity)

AsyncResult<EzDoneUploadResult> asyncResult = null;
var current = gs2.Datastore.DoneUpload(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    dataObjectName: "dataObject-0001" // data name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.DataObjectId); // data object
Debug.Log(item.Name); // Name of data
Debug.Log(item.UserId); // user ID
Debug.Log(item.Scope); // File access rights
Debug.Log(item.AllowUserIds); // User ID list to be published
Debug.Log(item.Status); // status
Debug.Log(item.Generation); // Data generation
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated date

helper function

GS2 SDK for Unity provides a helper function that combines the three-step upload process into a single API.

Helper function usage examples (Unity)

var current = gs2.Datastore.Upload(
    r =>
    {
        if (r.Error != null) throw r.Error;
        result = r.Result;
    },
    gameSession,    // GameSession Session object representing login state
    namespaceName, // namespace name
    scope, // file access rights
    allowUserIds, // list of user IDs to be published
    binary // binary data in byte array
);
yield return current;

Download Data

Downloading data consists of two steps.
- Obtain the URL for downloading
- Download data
Unlike uploading, there is no need to report completion, so this is a two-step process.

Get URL for download

The URL for download is obtained based on the user ID that raised the data and the name of the data.
The URL obtained here will be downloaded as a GET request with the HTTP client.

Implementation example
Obtaining URL for download (Unity/UniTask enabled)

var domain = gs2.Datastore.Namespace(
    namespaceName: "namespace1" // namespace name
).User(
    userId: "user-0001" // user ID
).DataObject(
    dataObjectName: "dataObject-0001" // Data name
);
var result = await domain.PrepareDownloadByUserIdAndDataObjectNameAsync(
);
var item = await result.ModelAsync();
var fileUrl = result.FileUrl;
var contentLength = result.ContentLength;

Debug.Log(item.DataObjectId); // data object
Debug.Log(item.Name); // name of data
Debug.Log(item.UserId); // user ID
Debug.Log(item.Scope); // File access rights
Debug.Log(item.AllowUserIds); // User ID list to be published
Debug.Log(item.Status); // status
Debug.Log(item.Generation); // Data generation
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated date
Debug.Log(fileUrl); // URL to download the file
Debug.Log(contentLength); // file size

Obtaining URL for download (Unity)

AsyncResult<EzPrepareDownloadByUserIdAndDataObjectNameResult> asyncResult = null;
var current = gs2.Datastore.PrepareDownloadByUserIdAndDataObjectName(
callback: r => { asyncResult = r; },
namespaceName: "namespace1", // namespace name
userId: "user-0001", // user ID
dataObjectName: "dataObject-0001" // data name );

yield return current; if (asyncResult.Error != null) {
OnError(asyncResult.Error);
yield break; }

var result = asyncResult.Result; var item = result.Item; var fileUrl = result.FileUrl; var contentLength = result.ContentLength;

Debug.Log(item.DataObjectId); // data object Debug.Log(item.Name); // name of data Debug.Log(item.UserId); // user ID Debug.Log(item.Scope); // File access rights Debug.Log(item.AllowUserIds); // User ID list to be published Debug.Log(item.Status); // status Debug.Log(item.Generation); // Data generation Debug.Log(item.CreatedAt); // Creation date and time Debug.Log(item.UpdatedAt); // Last updated date Debug.Log(fileUrl); // URL to download the file Debug.Log(contentLength); // file size

Download Data

Execute download to the obtained URL.
The download is performed using a GET request with an HTTP client to the file server, not GS2.

GS2-Deploy

Service Overview

This service assists in the deployment of services.

This service allows you to create resources for each GS2 service by applying a template describing the resources required by the game.
Resource management using GS2-Deploy makes it easy to align settings between development and production environments, and to create environments for each developer during development.
Also, when holding an event, you can easily return to the state before the event by creating a template of the elements required for the event, registering them, and then deleting them when the event is over.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

Example GS2-Deploy template issuing credentials

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10

Globals:
  Alias:
    ApplicationUserName: application

Resources:
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}

  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser

Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret

In GS2, basically, the creation of resources such as namespace creation and item definition is done one by one on the management console.
GS2-Deploy enables the creation of resources by describing the operations and inputs on the management console in a template file in YAML format.
As a feature of GS2-Deploy, if a part of the template file is added or deleted once input, it will be immediately reflected in the resource.
If the input template file itself is deleted, the resources created with that template file will be deleted.

Based on the above characteristics, the following uses are possible

GS2-Dictionary

Service Overview

Realize a database with binary values of "obtained" and "not obtained" for each player/entry, such as item and character index.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are three steps to use.

  1. Define the entry model
  2. Entry is "acquired" upon an event that results in the acquisition of an item, character, or other item.
  3. Get entries from within the game

Define the entry model

Define an entry model, such as from the management console, to represent the presence of items and characters.
At this time, it is recommended to separate namespaces for each type of illustration.
This is because when opening an illustrated book, a list of entries is retrieved, but for each namespace. When managing the experience of obtaining Items in GS2-Inventory with GS2-Dictionary, it is considered that matching ItemName and EntryName will make it easier to handle in your program.
In addition, although the usage is explained in terms of illustrated books, please utilize any information you wish to store on the server in a binary format, not limited to illustrated books.

Entry is "acquired" upon an event that results in the acquisition of an item, character, or other item

The security policy ApplicationAccess does not allow the client to report the acquisition of an entry in order to prevent the client from reporting a lie by cheating. If a GS2 event triggers the acquisition, please report the acquisition via StampSheet or GS2-Script.
Alternatively, you can report an acquisition to GS2 from the server.

Get entries from within the game

Build the UI by retrieving recorded entries from within the game.

GS2-Distributor

Service Overview

Provides a function to relay the property increase process and transfer it to GS2-Inbox when the upper limit of the target possession quantity is reached.
This function eliminates the complicated branching process when the upper limit of the possession quantity is reached, thereby avoiding the risk of unintended data loss.

In addition, this function is also used for the stamp sheet execution process, a mechanism to achieve consistent processing within GS2.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

This function is not an API call, but rather a configuration to be prepared.
There are two ways to use it.

Use for stamp sheet execution process

Use for stamp sheet execution process
GS2 uses a stamp sheet mechanism to handle increases and decreases in properties (in-game currency, stamina, possessions, etc.).
For more information on stamp sheets, see the Stamp Sheet section.
When executing a stamp sheet, the GS2-Distributor namespace is required as one of the arguments.
If you just want to run the stamp sheet, you only need to create the namespace.

Ability to transfer possession limit properties to GS2-Inbox

When executing a stamp sheet, the property's possession limit may be exceeded.
At this time, the exceeded properties can be automatically transferred to GS2-Inbox.
This one can be used by creating a Delivery Settings Master from the Management Console.
You can also specify which properties to transfer.
This can be used, for example, to avoid a situation in which the experience acquired at the experience limit continues to be transferred to the GS2-Inbox and it fills up.

GS2-Enhance

Service Overview

Provides a mechanism for consuming material items managed by GS2-Inventory and gaining experience in GS2-Experience.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

GS2-Exchange

Service Overview

It will realize a permanent exchange process, including the sale price of items and the exchange rate between evolutionary materials of different rarities.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Define an exchange model
  2. Perform the exchange

Define an exchange model

Set up the exchange model from the Management Console.
In addition to exchanging money for in-game currency, you can define various other ways to use in-game currency, such as to run gachas or increase stamina.

Perform the exchange

Example implementation for performing an exchange (Unity/UniTask enabled)

var domain = gs2.Exchange.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Exchange(
);
var result = await domain.ExchangeAsync(
    rateName: "rate-0001", // Name of exchange rate type
    count: 1, // Number of lots to exchange
    config: null // set value (optional)
);

var result = asyncResult.Result;
var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(Item.Name); // Name of exchange rate type
Debug.Log(Item.Metadata); // Metadata of exchange rate type
Debug.Log(Item.ConsumeActions); // Consume actions list
Debug.Log(Item.AcquireActions); // Acquire action list
Debug.Log(stampSheet); // Stamp sheet used to execute the exchange process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Example implementation to perform exchange (Unity)

AsyncResult<EzExchangeResult> asyncResult = null;
var current = gs2.Exchange.Exchange(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    rateName: "rate-0001", // Name of exchange rate type
    count: 1, // Number of lots to be exchanged
    config: null // config value (optional value)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(Item.Name); // Name of exchange rate type
Debug.Log(Item.Metadata); // Metadata of exchange rate type
Debug.Log(Item.ConsumeActions); // Consume actions list
Debug.Log(Item.AcquireActions); // Acquire action list
Debug.Log(stampSheet); // Stamp sheet used to execute the exchange process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

It is important to note that simply executing 'exchange' itself does not exchange resources.
It is done by processing the stamp sheet that is the return value of 'exchange'.
For more information on stamp sheets, see Stamp Sheet Overview
Please refer to the Stamp Sheet page.

If you want to set multiple rewards in one exchange model, you need to work with GS2-JobQueue.

GS2-Experience

Service Overview

It is used to realize a system of rank advancement by accumulating experience, such as character and skill levels and affinity.
It also has a rank cap function, which allows for management of upper limits for individual elements such as characters and skills.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Please limit the granting of experience to the same property to three times per second.
This limit does not apply to different users or to different properties for the same user.

Basic usage

GS2 offers GS2-Experience as a service to manage the growth of characters, items and skills.

GS2-Experience provides the following main functions

However, by linking with another GS2 service, such as GS2-Stamina, it is possible to extend the maximum value of stamina in conjunction with GS2-Experience ranks.

Experience Model Registration

The empirical value model is registered as master data in JSON format.
The format of the master data can be found at here.

Master data can also be prepared by registering data for each element in the Management Console and exporting the results.
Note that the exported master data is not reflected in GS2-Experience behavior until it is explicitly registered.

Experience Model Setup Values

The experience model represents the rank system, the type of growth factors such as character level and skill level.
The experience model allows for settings such as "which rank advancement threshold table to use," "default rank cap," and "limit for raising the rank cap.

Rank-up threshold table

The rank-up threshold table is an array of experience values that serve as the threshold for rank-up.
For example, if you set [100, 200, 300], then

Experience Value Rank
0 - 99 1
100 - 199 2
200 - 299 3
300 4

If a player attempts to gain experience beyond 300, the excess experience is rounded down.

Rank cap

Rank cap is the maximum rank that can be attained.
For example, if the values specified in the rank advancement threshold table are [100, 200, 300] and there are settings up to rank 4, but the rank cap is set to 2, the ranks that can be reached will be limited to 2, and no more experience will be available beyond 100.
The current rank cap value can be had for each individual character, skill, etc. as well as experience and current rank values.
The rank cap can be raised to the rank cap raising limit for each experience model, and raising the rank cap simultaneously extends the maximum amount of experience available.

Obtaining Experience

The current experience gained is retained for each experience model and property ID combination.

Therefore, when executing the process of obtaining experience, it is also necessary to specify a combination of the experience value model and property ID in addition to the amount of experience to be obtained.
The property ID is an identifier of the object to which the experience value is assigned, and can be specified as an arbitrary value without prior registration with GS2-Experience.

For example, if you want to give experience to a character managed by GS2-Inventory, you can specify the "possession ID" of GS2-Inventory as the property ID as it is.
If you want to give experience values to game players themselves, you can specify the "User ID" of GS2-Account as it is.

If you want a character to have multiple experience values, for example, "Combat Skill" and "Confidence," you can specify different experience value models to have multiple experience values for a single GS2-Inventory "Possession ID.
On the other hand, if you want to have multiple experience values for the same rank system of weapon skills, such as "Sword Skill" and "Bow Skill," you can prepare multiple experience value models with similar settings, or you can add strings such as -sword or -bow behind the "possession ID" in GS2-Inventory. Another method is to distinguish property IDs by adding

Experience Acquisition and Security

Obtaining experience is a sensitive operation.
Allowing clients to arbitrarily manipulate the experience they receive can lead to unauthorized experience accumulation and can seriously damage the gameplay.

Therefore, GS2 only allows experience to be obtained as stamp sheet rewards.
Stamp sheet rewards are defined on the server, and the stamp sheet system guarantees that payment has been made and in-game goals have been met before the reward is earned, thus preventing unauthorized proliferation of experience.
Therefore, experience rewards should be designed to be available for purchase in the in-game store or as quest rewards.

Get current experience

There are two ways to obtain experience

If you want to display the property pages of a particular character, the latter would be more efficient.

Get Experience Example Implementation (Unity/UniTask enabled)

var domain = gs2.Experience.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Status(
    experienceName: "character_ssr", // name of experience type
    propertyId: "property-0001" // property ID
);
var item = await domain.ModelAsync();

Debug.Log(item.ExperienceName); // name of experience type
Debug.Log(item.PropertyId); // property ID
Debug.Log(item.ExperienceValue); // Cumulative experience gained
Debug.Log(item.RankValue); // current rank
Debug.Log(item.RankCapValue); // current rank cap

Get Experience Example Implementation (Unity)

AsyncResult<EzGetStatusResult> asyncResult = null;
var current = gs2.Experience.GetStatus(
callback: r => { asyncResult = r; },
session: session, // GameSession object (access token)
namespaceName: "namespace1", // namespace name
experienceName: "character_ssr", // name of experience type
propertyId: "property-0001" // property ID );

yield return current; if (asyncResult.Error != null) {
OnError(asyncResult.Error);
yield break; }

var result = asyncResult.Result; var item = result.Item;

Debug.Log(item.ExperienceName); // name of experience type Debug.Log(item.PropertyId); // property ID Debug.Log(item.ExperienceValue); // Cumulative experience gained Debug.Log(item.RankValue); // current rank Debug.Log(item.RankCapValue); // current rank cap

TIPS: Experience awarded to characters organized in a party

GS2 provides GS2-Formation as a service for organizing multiple resources.
GS2-Formation can be used to assign experience values as rewards to all organized resources, without having to specify each resource individually.
This makes it easy to reward experience to all the characters in a party at once.

TIPS: Assure validity of status

In some use cases, such as opening up some functionality based on rank, you may want to verify that the rank value sent by the client is legitimate.
GS2-Experience responds to such needs with the ability to respond with a signed (*) status.

This feature allows the client to determine whether the value of the status sent by the client can be trusted without inter-server communication.
When performing operations using repeated statuses, passing signed statuses from the client to the server can reduce the number of communications and communication time.

However, the signed status is only the value at the time of acquisition, so if the status changes, the client must re-acquire the status before passing it to the server.
Signed statuses are assigned a response time, and GS2 services will not be able to use signed statuses that have been acquired for more than one hour.

GS2-Formation

Service Overview

equipment and party organization functions.

There are two types of forms: Forms, which record formation information, and Molded forms, which save the forms that have been formed.
For example, to organize a party, you can set the characters in a form and organize the party.
If you want to record multiple party information, you can use Saved Forms.

The number of saved forms can be set to a certain capacity, and the capacity value can be increased.

The properties organized in a form are specified by property IDs, but the values can be restricted by property regular expressions.
When setting up GS2-Inventory resources, you can also specify the organization target using a signed itemset issued by GS2-Inventory.
A signed itemset is property information with a signature that guarantees ownership of the item, and allows organization directly from the client.

This assurance of ownership is a guarantee at the time of composition, and there is no follow-up if the property is relinquished after composition.
If a property is to be consumed or sold in GS2-Inventory, the determination of whether or not it has been used for organization in GS2-Formation must be implemented in the client or in a script beforehand.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Update processing of the same form should be limited to no more than three times per second.

Basic usage

There are four steps to use.

  1. Define form model master data
  2. Define form storage area (Mold) model master data
  3. Create a form
  4. Save the form in the form storage area (Mold)

Define form model master data

Form model masters can be created in the Management Console.
For example, if you want to store party information for 5 characters, you can set up 5 slots and enter the slot model name as char1~5.
Note that only 10 slots can be set per form from the Management Console.
If you want to set more than 10 slots, please save the form with the missing slots, export the master data, edit it, and upload it.

Define form storage area (Mold) model master data

Mold model masters can be created in the Management Console.
The Mold model master determines how many forms can be stored according to the created form model master.
You can set the initial capacity and the maximum capacity.
For example, you can increase capacity as the game progresses or purchase capacity with in-game currency.

Create a form

Example of retrieving a signed itemset (Unity)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Inventory(
    inventoryName: "inventory-0001" // inventory type name
).ItemSet(
    itemName: "item-0001", // item model type name
    itemSetName: null // Name identifying the item set (optional)
);
var result = await domain.GetItemWithSignatureAsync(
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001" // cryptographic key GRN of the GS2-Key used to issue the signature
);
var item = await result.ModelAsync();
var itemModel = result.ItemModel;
var inventory = result.Inventory;
var body = result.Body;
var signature = result.Signature;

Debug.Log(items); // Item possession quantity list by expiration date
Debug.Log(itemModel.Name); // item model name
Debug.Log(itemModel.Metadata); // Item model metadata
Debug.Log(itemModel.StackingLimit); // Maximum stackable quantity
Debug.Log(itemModel.AllowMultipleStacks); // Whether to allow storing items in multiple stacks when the maximum stackable quantity is exceeded
Debug.Log(itemModel.SortValue); // display order
Debug.Log(inventory.InventoryId); // Inventory GRN
Debug.Log(inventory.InventoryName); // inventory model name
Debug.Log(inventory.CurrentInventoryCapacityUsage); // Current inventory capacity usage
Debug.Log(inventory.CurrentInventoryMaxCapacity); // maximum capacity of current inventory
Debug.Log(body); // Itemset information to be signed
Debug.Log(signature); // signature

Example implementation for retrieving a signed itemset (Unity)

AsyncResult<EzGetItemWithSignatureResult> asyncResult = null;
var current = gs2.Inventory.GetItemWithSignature(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    inventoryName: "inventory-0001", // inventory type name
    itemName: "item-0001", // Item model type name
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001", // cryptographic key GRN of the GS2-Key used to issue the signature
    itemSetName: null // Name identifying the item set (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var items = result.Items;
var itemModel = result.ItemModel;
var inventory = result.Inventory;
var body = result.Body;
var signature = result.Signature;

Debug.Log(items); // Item possession quantity list by expiration date
Debug.Log(itemModel.Name); // item model name
Debug.Log(itemModel.Metadata); // Item model metadata
Debug.Log(itemModel.StackingLimit); // Maximum stackable quantity
Debug.Log(itemModel.AllowMultipleStacks); // Whether to allow storing items in multiple stacks when the maximum stackable quantity is exceeded
Debug.Log(itemModel.SortValue); // display order
Debug.Log(inventory.InventoryId); // Inventory GRN
Debug.Log(inventory.InventoryName); // inventory model name
Debug.Log(inventory.CurrentInventoryCapacityUsage); // Current inventory capacity usage
Debug.Log(inventory.CurrentInventoryMaxCapacity); // maximum capacity of current inventory
Debug.Log(body); // Itemset information to be signed
Debug.Log(signature); // signature

Example of creating a list of slots with signatures (Unity)

List<EzSlotWithSignature> slots = new List<EzSlotWithSignature>();
EzSlotWithSignature slot = new EzSlotWithSignature();
slot.Name = "chara1"; //name the slot (e.g., for a party of 5 characters, create chara1 through chara5)
slot.PropertyType = "gs2_inventory"; // property type gs2_inventory property used
slot.Body = result.Body; // Payload
Signature = result.Signature; // Signature proving ownership of the property ID resource
slots.Add(slot); // actually create and add as many slots as there are slots in the form

As a basic usage example, the following is an example of creating a form by organizing possessions managed by GS2-Inventory on the client side.
In this case, a 'signed item set' issued by GS2-Inventory is used to prevent the organization of items that are not in the client's possession.
This is then applied to the 'list of signed slots' to create the form.

Save the form in the form storage area (Mold)

Example of creating a list of signed slots (Unity/UniTask enabled)

var domain = gs2.Formation.Namespace(
    namespaceName: "namespace2" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Mold(
    moldName: "mold-0001" // name of the form storage area
).Form(
    index: 0 // index of storage area
);
var result = await domain.SetFormAsync(
    slots: new Gs2.Unity.Gs2Formation.Model.EzSlotWithSignature[] {
        {'name': 'slot-0001', 'propertyType': 'gs2_dictionary', 'body': 'body', 'signature': 'signature'}
    }, // List of slots to be organized
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001" // cryptographic key GRN of the GS2-Key used to issue the signature
);
var item = await result.ModelAsync();
var mold = result.Mold;
var moldModel = result.MoldModel;
var formModel = result.FormModel;

Debug.Log(Item.Name); // name of form storage area
Debug.Log(Item.Index); // index of storage area
Debug.Log(Item.Slots); // Slot list
Debug.Log(Mold.Name); // name of form storage area
Debug.Log(Mold.UserId); // user ID
Debug.Log(Mold.Capacity); // current capacity
Debug.Log(MoldModel.Name); // name of form storage area
Debug.Log(MoldModel.Metadata); // metadata
Debug.Log(MoldModel.FormModel.Name); // name of form type
Debug.Log(MoldModel.FormModel.Metadata); // Metadata of form type
Debug.Log(MoldModel.FormModel.Slots); // slit list
Debug.Log(MoldModel.InitialMaxCapacity); // Initial capacity at which the form can be saved
Debug.Log(MoldModel.MaxCapacity); // Capacity to store the form
Debug.Log(FormModel.Name); // name of form type
Debug.Log(FormModel.Metadata); // Metadata of form type
Debug.Log(FormModel.Slots); // Slot list

Example of creating a list of signed slots (Unity)

AsyncResult<EzSetFormResult> asyncResult = null;
var current = gs2.Formation.SetForm(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace2", // namespace name
    moldName: "mold-0001", // name of form storage area
    index: 0, // index of storage area
    slots: new Gs2.Unity.Gs2Formation.Model.EzSlotWithSignature[] {
        {'name': 'slot-0001', 'propertyType': 'gs2_dictionary', 'body': 'body', 'signature': 'signature'}
    }, // list of slots to organize
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace1:key:key-0001" // cryptographic key GRN of the GS2-Key used to issue the signature
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var mold = result.Mold;
var moldModel = result.MoldModel;
var formModel = result.FormModel;

Debug.Log(item.Name); // name of form storage area
Debug.Log(item.Index); // index of storage area
Debug.Log(item.Slots); // Slot list
Debug.Log(mold.Name); // name of form storage area
Debug.Log(mold.UserId); // user ID
Debug.Log(mold.Capacity); // current capacity
Debug.Log(moldModel.Name); // name of form storage area
Debug.Log(moldModel.Metadata); // metadata
Debug.Log(moldModel.FormModel.Name); // name of form type
Debug.Log(moldModel.FormModel.Metadata); // Metadata of form type
Debug.Log(moldModel.FormModel.Slots); // slit list
Debug.Log(moldModel.InitialMaxCapacity); // Initial capacity at which the form can be saved
Debug.Log(moldModel.MaxCapacity); // Capacity to store the form
Debug.Log(formModel.Name); // name of form type
Debug.Log(formModel.Metadata); // Metadata of form type
Debug.Log(formModel.Slots); // Slot list

Execute setForm with the created 'list of signed slots' as an argument.
The encryption key used to issue the 'signed itemset' is also specified as an argument.

GS2-Friend

Service Overview

It is used to realize in-game friendships.

There are two types of friends: friends that can be established only after a request is made and approved, and follows that can be established without the approval process of the other party.

Profile information can be included as metadata for game players.
Profile information has a scope of public public to followers public to friends and is made public to other players according to the scope.

The maximum number of friends and followers is 10,000 each, but additional restrictions may be added depending on the policy of each service you are connecting to.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Profile updates by the same game player should be limited to 3 times per second.
This limit does not apply to different users or to the same user granting experience to different properties.

Avoid concentrating friend requests on a single player.
A player can only receive 3 friend requests per second.

Basic usage

There are three main ways to use it.

Profile

Implementation example : Set up your profile (Unity/UniTask enabled)

var domain = gs2.Friend.Namespace(
    namespaceName: "namespace2" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Profile(
);
var result = await domain.UpdateProfileAsync(
    publicProfile: "public", // public profile (optional)
    followerProfile: "follower", // public profile for followers (optional)
    friendProfile: "friend" // public profile for friends (optional)
);
var item = await result.ModelAsync();

Debug.Log(item.UserId); // User ID
Debug.Log(item.PublicProfile); // public profile
Debug.Log(item.FollowerProfile); // public profile for followers
Debug.Log(item.FriendProfile); // Public profile for friends

Implementation example : Set up your profile (Unity)

AsyncResult<EzUpdateProfileResult> asyncResult = null;
var current = gs2.Friend.UpdateProfile(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace2", // namespace name
    publicProfile: "public", // public profile (optional)
    followerProfile: "follower", // public profile for followers (optional)
    friendProfile: "friend" // public profile for friends (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.UserId); // User ID
Debug.Log(item.PublicProfile); // public profile
Debug.Log(item.FollowerProfile); // public profile for followers
Debug.Log(item.FriendProfile); // Public profile for friends

Example of setting up a profile (Unity)

yield return gs2.Friend.UpdateProfile(
    r => {
        if (r.Error ! = null)
        {
            // Reached if an error occurs
            // r.Error contains the exception object that occurred
        }
        else
        {
            Debug.Log(r.Result.Item.UserId); // string user ID
            Debug.Log(r.Result.Item.PublicProfile); // string Public profile
            Debug.Log(r.Result.Item.FollowerProfile); // string Profile published for followers
            Debug.Log(r.Result.Item.FriendProfile); // string Profile published for friends
        }
    },
    gameSession,    // GameSession Session object representing login state
    namespaceName, // namespace name
    publicProfile, // profile to be made public (optional value)
    followerProfile, // public profile for followers (optional value)
    friendProfile // public profile for friends (optional value)
);

Set the information to be made public to others.
You can set the information for all, followers, and friends respectively.

Follow

Example of following (Unity)

yield return gs2.Friend.Follow(
    r => {
        if (r.Error ! = null)
        {
            // Reached if an error occurs
            // r.Error contains the exception object that occurred
        }
        else
        {
            Debug.Log(r.Result.Item.UserId); // string user ID
        }
    },
    gameSession,    // GameSession Session object representing login state
    namespaceName, // namespace name
    targetUserId, // user ID to be followed
);

A follow is a relationship that can be established without the approval process of the other party. You can also unfollow.
When you follow a player, you will get a list of the players you have followed and their messages to their followers.

Friend

A friend is a relationship that is established by submitting a request and being approved.

What the person making the request can do is

What the recipient of the request can do is

GS2-Gateway

Service Overview

GS2-Gateway provides a proxy function to access GS2 via WebSocket.
By using GS2-Gateway to access GS2's servers, you can communicate with them while staying connected at all times. This is expected to improve the communication speed with the server.

This will also allow for push notifications from the server side.
With this push notification functionality, you will be able to receive notifications when a task in a GS2-Mission is completed, or when the number of participants in a GS2-Matchmaking Gathering increases or decreases.

If the device being notified is offline, the system also provides a mechanism for forwarding to mobile push notifications using Firebase (https://firebase.google.com/).
With this feature, if a player is offline when matchmaking is completed, a mobile push notification can be sent out to entice the player to return to the game.

When building an always-on session with GS2-Gateway, you will need to authenticate with an access token issued by GS2-Auth to identify the game player, but you can also use the
If a session already exists for the same user, access can be denied.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

This 3-step guide explains the process from making WebSocket communications to receiving push notifications.

  1. Start WebSocket communication
  2. Configure the server to send push notifications
  3. Define what to do when you receive a push notification

WebSocket communication

Example of initiating WebSocket communication (Unity/UniTask enabled)

var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).WebSocketSession(
);
var result = await domain.SetUserIdAsync(
    allowConcurrentAccess: null // allow connections from different clients at the same time?
);
var item = await result.ModelAsync();

Debug.Log(item.ConnectionId); // connection ID
Debug.Log(item.NamespaceName); // namespace name
Debug.Log(item.UserId); // user ID

Example of initiating WebSocket communication (Unity)

AsyncResult<EzSetUserIdResult> asyncResult = null;
var current = gs2.Gateway.SetUserId(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    allowConcurrentAccess: null // allow connections from different clients at the same time?
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.ConnectionId); // connection ID
Debug.Log(item.NamespaceName); // namespace name
Debug.Log(item.UserId); // user ID

Configure the server to send push notifications

There are three ways to send push notifications.

  1. Use push notifications provided by GS2
  2. Using GS2-Script
  3. Using GS2 SDK from your own server

Use push notifications provided by GS2

You can use the push notifications provided by GS2, such as when a task in a GS2-Mission is completed, or when the number of participants in a GS2-Matchmaking gathering increases or decreases.
You can configure whether or not to receive push notifications from the namespace of the service that sends push notifications.
For example, when a Gathering match is completed in GS2-Matchmaking, the message Gs2Matchmaking:Complete is sent.

Using GS2-Script

Use this if you want to send push notifications from GS2 events that do not provide push notifications, or if you want to decide the content of the message yourself.
Please check GS2-Script for details.

Using GS2 SDK from your own server

If you wish to send push notifications triggered by events other than GS2 events, please use this method.

Example of sending push notifications from a server (Python)

from gs2_gateway_client.request import SendNotificationRequest
from gs2_gateway_client.result import SendNotificationResult

result = client.send_notification(
    SendNotificationRequest()\
        .with_namespace_name(namespace_name)\
        .with_user_id(user_id)\
        .with_subject(subject)\
        .with_payload(payload)\
        .with_enable_transfer_mobile_notification(enable_transfer_mobile_notification)\
        .with_sound(sound)
)
# Exception is raised when an error occurs
# result contains the success result

Define what to do when you receive a push notification

Example of defining processing when a push notification is received (Unity)

// Define a function to run when a push notification arrives
public void PushNotificationHandler(NotificationMessage message)
{
    Debug.Log(message.issuer); //Event caused by push notification
    Debug.Log(message.subject); //title of push notification
    Debug.Log(message.payload); //Content of push notification

    if (message.issuer.StartsWith("Gs2Matchmaking:")){
        if (message.issuer.EndsWith(":Join"))
        {
            //Processing when new participants are added to the Gathering
            var notification = JoinNotification.FromJson(JsonMapper.ToObject(message.payload));
            Debug.Log(notification.JoinUserId); //ID of the user who newly joined the gathering
        }
        else if (message.issuer.EndsWith(":Leave"))
        {
            //Processing when the number of participants decreases from the Gathering
            var notification = LeaveNotification.FromJson(JsonMapper.ToObject(message.payload));
            Debug.Log(notification.LeaveUserId); //ID of the user who left the gathering
        }
        else if (message.issuer.EndsWith(":Complete"))
        {
            //Processing when matching is completed
        }
    }
}

// Set the defined function to be called when a push notification arrives
Gs2Client.profile.Gs2Session.OnNotificationMessage += PushNotificationHandler;

Finally, define how the client will handle push notifications when they arrive.
Here is an example using the push notification provided in GS2-Matchmaking.

GS2-Identifier

Service Overview

This function manages credentials and privileges for accessing GS2.

When accessing GS2, credentials are used to call the API.
The processing is based on the security policy assigned to the user who owns the credential.
If multiple security policies are assigned to a user, the API can be used as long as one of the security policies allows the operation.

Multiple people can manage a single project by creating management console login passwords.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

The usage is divided into three steps.

  1. Prepare a security policy
  2. Create users and assign security policies
  3. Call the API or log in to the management console with the user you created

Prepare a security policy

From the beginning, GS2 provides two access privileges: AdministratorAccess for developers to use all APIs, and ApplicationAccess for users to call only those APIs that do not lead to cheating.
It is also possible to create security policies.

Policy Document Format
List the actions that can be called in Actions and the target resources that can be manipulated in Resources.
Actions / Resources can only use trailing wildcards

{
    'Version': '2016-04-01',
    'Statements': [
        {
            'Effect': 'Allow',
            'Actions': [
                'Gs2Account:Create*',
            ],
            'Resources': ['*'],
        },
    ]
}

Create users and assign security policies

Once the security policy is ready, create users.
A user can be assigned multiple security policies.
In this case, the user will be able to execute APIs that are allowed under one of the security policies.

Calling the API with the created user

Example of authenticating a user using credentials (Unity)

    var profile = new Gs2.Unity.Util.Profile(
        clientId: 'credential ID',
        clientSecret: 'credential password',
        reopener: new Gs2BasicReopener()
    );

    {
        AsyncResult<object> asyncResult = null;
        var current = profile.Initialize(
            r => { asyncResult = r; }
        );
        yield return current;
    {
    var gs2 = new Gs2.Unity.Client(profile); // Various APIs can be called using gs2 (Gs2.Unity.Client)

After creating a user, create credentials.
Credentials are IDs and passwords that authenticate the user's identity.
By incorporating this ID and password into your program and requesting authentication from GS2, you will be able to use the API.

Login to the Management Console with the created user

A management console login password allows another developer to log in to the management console.
Once the password is created, a login URL will be generated, and the two can be notified to another developer to log in.
The functions available are limited by the security policy assigned to the user.

GS2-Inbox

Service Overview

This service provides a message function with a gift.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are four steps to use.

  1. Make a gift box
  2. Send a message
  3. Receive messages
  4. Receive the reward attached to the message.

Make a gift box

The name space directly serves as a gift box.
If you wish to have separate gift boxes for each type of message, please create multiple name spaces.

Send a message

Example of sending individual messages (Python)

from gs2_inbox_client.request import SendMessageByUserIdRequest
from gs2_inbox_client.result import SendMessageByUserIdResult

result = client.send_message_by_user_id(
    SendMessageByUserIdRequest()\
        .with_namespace_name('namespace-0001')\
        .with_user_id('user-0001')\
        .with_metadata('{"type": "message", "body": "hello"}')\
        .with_read_acquire_actions(read_acquire_actions)\
        .with_expires_at(expires_at)\
        .with_expires_time_span(expires_time_span)
)
# Exception is raised in case of error
# result contains the success result

Example of receiving an overall message (Python)

from gs2_inbox_client.request import CreateGlobalMessageMasterRequest
from gs2_inbox_client.result import CreateGlobalMessageMasterResult

result = client.create_global_message_master(
    CreateGlobalMessageMasterRequest()\
        .with_namespace_name('namespace-0001')\
        .with_name('globalMessageMaster-0001')\
        .with_metadata('{"type": "globalMessageMaster", "body": "hello"}')\
        .with_read_acquire_actions([
Object("AcquireAction", {"action": 'Gs2Inventory:AcquireItemSetByUserId', "request": 'Gs2Inventory:AcquireItemSetByUserId-request'})
])\
        .with_expires_time_span(expires_time_span)\
        .with_expires_at(expires_at)
)
# Exception is raised in case of error
# result contains the success result

There are two transmission methods.

Messages can be sent from the server using the GS2 SDK or from the management console.
Messages can also be accompanied by a reward.

Receive messages

The point to note here is that the APIs for receiving individual messages and global messages are different.
Once a global message is received, it is stored as an individual message.

Example of receiving individual messages (Unity/UniTask enabled)

var domain = gs2.Inbox.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession //  GameSession object (access token)
);
var items = await domain.MessagesAsync(
).ToListAsync();

Debug.Log(items); // List of messages

Example of receiving individual messages (Unity)

AsyncResult<EzListResult> asyncResult = null;
var current = gs2.Inbox.List(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    limit: null, // Number of data retrieved (optional)
    pageToken: null // Token specifying the position from which to start acquiring data (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var items = result.Items;
var nextPageToken = result.NextPageToken;

Debug.Log(items); // List of messages
Debug.Log(nextPageToken); // Page token to retrieve the rest of the listing

Example implementation of receiving an overall message (with Unity/UniTask enabled)

var domain = gs2.Inbox.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var result = await domain.ReceiveGlobalMessageAsync(
);
var item = await result.ModelAsync();

Debug.Log(Item); // List of received messages

Example of receiving an overall message (Unity)

AsyncResult<EzReceiveGlobalMessageResult> asyncResult = null;
var current = gs2.Inbox.ReceiveGlobalMessage(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1" // namespace name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(Item); // List of received messages

Receive the reward attached to the message

Example of receiving a reward attached to a message (Unity)

var domain = gs2.Inbox.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Message(
    messageName: "message-0001" // message name
);
var result = await domain.ReadAsync(
);

var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(item.MessageId); // message GRN
Debug.Log(item.Name); // message name
Debug.Log(item.Metadata); // metadata corresponding to the message content
Debug.Log(item.IsRead); // read status
Debug.Log(item.ReadAcquireActions); // acquire actions to be performed upon opening
Debug.Log(item.ReceivedAt); // Creation date and time
Debug.Log(item.ReadAt); // Last modified date
Debug.Log(item.ExpiresAt); // message expiration date
Debug.Log(stampSheet); // stamp sheet
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Example of receiving a reward attached to a message (Unity)

AsyncResult<EzReadResult> asyncResult = null;
var current = gs2.Inbox.Read(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    messageName: "message-0001" // message name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(item.MessageId); // message GRN
Debug.Log(item.Name); // message name
Debug.Log(item.Metadata); // metadata corresponding to the message content
Debug.Log(item.IsRead); // read status
Debug.Log(item.ReadAcquireActions); // acquire actions to be performed upon opening
Debug.Log(item.ReceivedAt); // Creation date and time
Debug.Log(item.ReadAt); // Last modified date
Debug.Log(item.ExpiresAt); // message expiration date
Debug.Log(stampSheet); // stamp sheet
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Messages may have rewards attached to them.
By executing the API to mark a message as read, a stamp sheet with the contents of the reward is obtained.
By executing this stamp sheet, you will get the reward.
For more information on stamp sheets, please refer to the How to Stamp Sheet page.
Note that the 'messageName' argument in the sample code should be 'name', not 'messageId' of the 'message' received.
Also, if you want to set multiple rewards for a single message, you need to work with GS2-JobQueue.

GS2-Inventory

Service Overview

Provides the ability to manage possessions.

The bag-like entity that holds items is called inventory.
Inventory can have a capacity, which can be expanded later.
You can expand your inventory capacity by spending currency or by receiving rewards from quests.

Items can have an expiration date.
Expired items can no longer be used, and if you do not explicitly specify an expiration date when using an item, it will be consumed from the item closest to its expiration date.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Provides the ability to manage possessions.

The bag-like entity that holds items is called inventory.
Inventory can have a capacity, which can be expanded later.
You can expand your inventory capacity by spending currency or by receiving rewards from quests.

Items can have an expiration date.
Expired items can no longer be used, and if you do not explicitly specify an expiration date when using an item, it will be consumed from the item closest to its expiration date.

Basic usage

GS2 provides a service called GS2-Inventory as a mechanism for managing possessions.
There are many different types of in-game elements that can be considered possessions, and GS2-Inventory is designed to handle them all.
For example

GS2-Inventory manages only the quantity possessed, and the implementation of the effects of use would be based on a resource exchange design (e.g., a reward that restores stamina value in exchange for a stamina drink) using GS2-Exchange or similar.

inventory / item set

Example of inventory acquisition (Unity/UniTask enabled)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Inventory(
    inventoryName: "inventory-0001" // Inventory type name
);
var item = await domain.ModelAsync();

Debug.Log(item.InventoryId); // inventory
Debug.Log(item.InventoryName); // inventory model name
Debug.Log(item.CurrentInventoryCapacityUsage); // current inventory capacity usage
Debug.Log(item.CurrentInventoryMaxCapacity); // maximum capacity of current inventory

Example of inventory acquisition (Unity)

AsyncResult<EzGetInventoryResult> asyncResult = null;
var current = gs2.Inventory.GetInventory(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    inventoryName: "inventory-0001" // Inventory type name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.InventoryId); // inventory
Debug.Log(item.InventoryName); // inventory model name
Debug.Log(item.CurrentInventoryCapacityUsage); // current inventory capacity usage
Debug.Log(item.CurrentInventoryMaxCapacity); // maximum capacity of current inventory

GS2-Inventory has the concept of the item set and inventory as units for managing possessions. An item set is a combination of the type of item and its quantity, such as "Stamina Drink x 1" or "Wound Medicine x 30.
Inventory is like a bag that stores item sets.
When actually used in a game, it is effective to divide the inventory into categories that you want to list in the UI, such as characters, consumer goods, and currency.

Example of acquiring items in possession (Unity/UniTask enabled)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Inventory(
    inventoryName: "item" // name of inventory type
);
var items = await domain.ItemSetsAsync(
).ToListAsync();

Debug.Log(items); // List of item possession quantities by expiration date

Example of acquiring items in possession (Unity)

AsyncResult<EzListItemsResult> asyncResult = null;
var current = gs2.Inventory.ListItems(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    inventoryName: "item", // name of inventory type
    limit: null, // number of data to be retrieved (optional)
    pageToken: null // token specifying where to start retrieving data (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var items = result.Items;
var nextPageToken = result.NextPageToken;

Debug.Log(items); // List of item possession quantities by expiration date
Debug.Log(nextPageToken); // page token to get the rest of the list
);

Personal belongings allowance

The inventory has a possession quota, and each item set occupies one possession quota.
The number of inventory slots is finite and cannot be exceeded.
The number of inventory slots is expandable per game player, and can be designed to be expanded with the use of currency or resources.

Multiple possession of the same item

GS2-Inventory allows you to set the maximum number of items that can be stored in an item set for each type of item.
For items such as characters and equipment that need to be individually distinguished, this maximum number should be set to 1.
On the other hand, for items that are supposed to be held in large quantities, such as consumables and enhancement materials, the number should be set to 99, 999, etc.

For each type of item, you can also set whether you can create multiple item sets for that item.
By enabling this setting, you can have more than the maximum number of items per item set by occupying multiple possession slots.

Depending on the characteristics of the item type, the following settings are possible, for example

Item Type Maximum number of items that can be stored in one item set Can multiple sets of the same type of items be created?
Characters, equipment, etc. 1 OK
Consumables and strengthening materials 99 OK
in-game currency 999999999 NG

effective date

You can set an expiration date for your possessions. Expired possessions will be deleted on their own. You can use items that can only be used during the event period, or distribute stamina drinks as a login bonus that can only be used on the same day.

Items of the same type but with different expiration dates will create separate item sets.
In such cases, items that are set to prevent the creation of multiple item sets of the same type may not be available.

Registration of inventory and item models

Inventory and item models are registered as master data in JSON format.

Master data can also be prepared by registering data for each element in the Management Console and exporting the results.
Note that the exported master data is not reflected in GS2-Inventory's behavior until it is explicitly registered.

Obtaining Items

If the full amount of an item cannot be obtained because it does not fit in the item set or there are not enough inventory slots available, only the full amount will be stored in the inventory and the overflowing number will be responded to.
The overflow items can be transferred to the gift box by using a script set in the namespace or GS2-Distributor.

If you specify that you always create a new item set, then if the new item set does not fill your inventory, it is treated as an overflow, even if there is room in the existing item set.

When an item set is specified to store an item, if the item set does not contain the item, it is treated as overflowing, even if there is room in other item sets or in the inventory.
An error will also occur if the contents of the specified item set do not match the type or expiration date of the item you are trying to obtain.

If none is specified, items are stored in such a way that they occupy the fewest number of inventory slots.

Item Acquisition and Security

Obtaining items is a sensitive operation.
Allowing clients to arbitrarily manipulate item acquisition can lead to the unauthorized proliferation of items, which can seriously damage the gameplay.

Therefore, GS2 only allows items to be obtained as rewards on stamp sheets.
The content of stamp sheet rewards is defined on the server, and the stamp sheet mechanism guarantees that payment has been made and in-game goals have been met before the reward is earned, thus preventing unauthorized proliferation of items.
Therefore, the rewards should be designed so that items can be obtained by purchasing them from the in-game store or as rewards for quests.

Item Consumption

The GS2 philosophy is that items should be consumed in exchange for stamp sheets.
However, GS2 provides an API for consumption so that rewards can be given for local resources.

Example of item consumption (Unity/UniTask enabled)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Inventory(
    inventoryName: "inventory-0001" // name of inventory
).ItemSet(
    itemName: "item-0001", // name of the item model
    itemSetName: null // name identifying the item set
);
var result = await domain.ConsumeAsync(
    consumeCount: 1L // volume to consume
);
var item = await result.ModelAsync();
var itemModel = result.ItemModel;
var inventory = result.Inventory;

Debug.Log(items); // list of item possession quantities by expiration date after consumption
Debug.Log(itemModel.Name); // name of the item model type
Debug.Log(itemModel.Metadata); // item model type metadata
Debug.Log(itemModel.StackingLimit); // maximum stackable quantity
Debug.Log(itemModel.AllowMultipleStacks); // Whether to allow storing items in multiple stacks when the maximum stackable quantity is exceeded
Debug.Log(itemModel.SortValue); // display order
Debug.Log(inventory.InventoryId); // inventory
Debug.Log(inventory.InventoryName); // inventory model name
Debug.Log(inventory.CurrentInventoryCapacityUsage); // current inventory capacity usage
Debug.Log(inventory.CurrentInventoryMaxCapacity); // maximum capacity of current inventory

Example of item consumption (Unity)

AsyncResult<EzConsumeResult> asyncResult = null;
var current = gs2.Inventory.Consume(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    inventoryName: "inventory-0001", // name of inventory
    itemName: "item-0001", // name of item model
    consumeCount: 1L, // volume to consume
    itemSetName: null // name identifying the item set
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var items = result.Items;
var itemModel = result.ItemModel;
var inventory = result.Inventory;

Debug.Log(items); // list of item possession quantities by expiration date after consumption
Debug.Log(itemModel.Name); // name of the item model type
Debug.Log(itemModel.Metadata); // Item model type metadata
Debug.Log(itemModel.StackingLimit); // maximum stackable quantity
Debug.Log(itemModel.AllowMultipleStacks); // whether to allow storing items in multiple stacks when the maximum stackable quantity is exceeded
Debug.Log(itemModel.SortValue); // display order
Debug.Log(inventory.InventoryId); // inventory
Debug.Log(inventory.InventoryName); // inventory model name
Debug.Log(inventory.CurrentInventoryCapacityUsage); // current inventory capacity usage
Debug.Log(inventory.CurrentInventoryMaxCapacity); // maximum capacity of current inventory

When an item set that consumes items is specified, if the number of items stored in the specified item set is not sufficient, it is treated as an insufficient number, even if there are extra items in other item sets.

If you do not specify an item set to consume an item, you can consume an item across multiple item sets.
In this case, the item set with the earliest expiration date will be used first.

GS2-JobQueue

Service Overview

This service provides a job queue function.

A job queue is a queue with a guaranteed FIFO and can be used for result matching.
Result matching is a mechanism in which processing is not guaranteed to be complete when the API responds, but "results in the intended state" after a certain amount of time has elapsed.

In GS2, a large portion of the rewarding process is performed in a result-aligned manner.
This is to avoid the possibility of various services becoming unavailable in the same way as if the server that manages the rewards were down when the rewards are granted.
The process of granting rewards is registered in a job queue, and even if the target server is unavailable when the job is executed, the results are reconciled by retrying the job.
The maximum number of retries can be specified, and if the maximum number is reached and the job does not succeed, it is stored in a model that accumulates failed jobs called dead letter jobs.
The dead letter jobs can be used to provide individualized handling of jobs that have failed.

GS2-JobQueue jobs do not execute on their own, but require an explicit call to the execution API.
The purpose of this is so that the return value of the job can be known on the client side.
For example, after completing a quest on GS2-Quest, a job that grants rewards is registered in the job queue, and a job that grants rewards is created in the job queue.
The client can explicitly execute the process of granting rewards obtained by the quest by running the job queue to the end.
(In addition, the UI can reflect the reward obtained by referring to the job's return value.

A job can only be registered and executed up to 3 times per second.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Job registration to the queue for the same user should be limited to three times per second.
Up to 10 jobs can be registered at one time, so please be creative.
Job execution should be limited to once per second.
This limit does not apply to jobs for different users.

Basic usage

It is to be used when multiple rewards are generated in a single transaction.
Examples include the sale of multiple sets of items or a 10-round gacha.

Two steps to use

  1. Namespace Settings
  2. Job Execution

Namespace Settings

First, create a namespace for GS2-JobQueue, a place to store jobs.
Next, specify the namespace of GS2-JobQueue where the job will be sent from the namespace of the service from which the job originates.
For example, there is a namespace setting for GS2-Exchange.
To specify the namespace of the destination GS2-JobQueue in the namespace of the originator of the job, use the
Multiple GS2-JobQueue namespaces can be created to manage jobs by sender.

You can also set up push notifications when jobs are added. Please refer to GS2-Gateway.

Job Execution

Example of executing a job (Unity)

AsyncResult<EzRunResult> asyncResult = null;
var current = gs2.JobQueue.Run(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace2" // namespace name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var result = result.Result;
var isLastJob = result.IsLastJob;

Debug.Log(item.JobId); // Job GRN
Debug.Log(item.ScriptId); // GRN of the script used to execute the job
Debug.Log(item.Args); // Arguments
Debug.Log(item.CurrentRetryCount); // Current retry count
Debug.Log(item.MaxTryCount); // maximum number of tries
Debug.Log(result.TryNumber); // number of attempts
Debug.Log(result.StatusCode); // status code
Debug.Log(result.Result); // Response content
Debug.Log(result.TryAt); // Date and time of execution
Debug.Log(isLastJob); // whether the end of job queue

Use run to execute a job. Note that one run executes only one job.
If the return value isLastJob is false, the job still remains.

GS2-Key

Service Overview

Service to manage encryption keys

Create encryption keys for confidential data in GS2 and for signature creation.
Since encryption key data cannot be taken out of GS2, it can be processed securely.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

It is not to be used independently, but to be called from each service.

GS2-Limit

Service Overview

Service to realize limit processing

This service is not used by itself, but is used in conjunction with other services to realize the limit function.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Please limit the number of operations on the same counter to 3 operations per second.
This limit does not apply to operations on different counters by different users or even by the same user.

Basic usage

Three steps to use

  1. Create a frequency limit master
  2. Increase counter
  3. Obtain the value of the counter

Create a frequency limit master

It can be created from the Management Console.
You can set the name of the counter and whether it will be reset periodically.

Increase counter

There are three ways to increase the counter.

Calling the API from the client

Count up from client Example implementation (Unity/UniTask enabled)

var domain = gs2.Limit.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Counter(
    limitName: "daily", // the frequency limit type name
    counterName: "counter1" // counter name
);
var result = await domain.CountUpAsync(
    countUpValue: 1, // amount to count up (optional)
    maxValue: 100 // maximum value allowed to count up (optional)
);
var item = await result.ModelAsync();

Debug.Log(item.CounterId); // counter GRN
Debug.Log(item.Name); // counter name
Debug.Log(item.Count); // count value
Debug.Log(item.CreatedAt); // creation date and time
Debug.Log(item.UpdatedAt); // last updated date

Example of counting up from client (Unity)

AsyncResult<EzCountUpResult> asyncResult = null;
var current = gs2.Limit.CountUp(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    limitName: "daily", // the frequency limit type name
    counterName: "counter1", // counter name
    countUpValue: 1, // amount to count up (optional)
    maxValue: 100 // maximum value allowed to count up (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.CounterId); // counter GRN
Debug.Log(item.Name); // counter name
Debug.Log(item.Count); // count value
Debug.Log(item.CreatedAt); // creation date and time
Debug.Log(item.UpdatedAt); // last updated date

This is a method in which the client requests GS2 to count up when the corresponding action is taken.
One point to note is that users may make unauthorized API calls when it is advantageous to count up.
If you want to avoid this, set a policy so that the GS2-Identifier cannot call count-up.

Set as a reward when GS2 event occurs

For example, you can set up a count-up as a reward for completing a Quest Model Master quest.
It can also be set to reward failure and count up regardless of the success or failure of the quest.
Another use is to count up the number of purchases by setting it as a reward for product purchases.

Calling the API from the server

Example of counting up from server (python)

from gs2_limit_client.request import CountUpByUserIdRequest
from gs2_limit_client.result import CountUpByUserIdResult

result = client.count_up_by_user_id(
    CountUpByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_limit_name(limit_name)\
        .with_counter_name(counter_name)\
        .with_user_id(user_id)\
        .with_count_up_value(count_up_value)\
        .with_max_value(max_value)
)

Called from your own server. This is safer than calling the API from the client.

Obtain the value of the counter

Implementation example : Obtain the value of the counter (Unity/UniTask enabled)

var domain = gs2.Limit.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Counter(
    limitName: "daily", // the frequency limit type name
    counterName: "counter1" // counter name
);
var item = await domain.ModelAsync();

Debug.Log(item.CounterId); // counter
Debug.Log(item.Name); // counter name
Debug.Log(item.Count); // count value
Debug.Log(item.CreatedAt); // creation date and time
Debug.Log(item.UpdatedAt); // last updated date

Implementation example : Obtain the value of the counter (Unity)

AsyncResult<EzGetCounterResult> asyncResult = null;
var current = gs2.Limit.GetCounter(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    limitName: "daily", // Name of the frequency limit type
    counterName: "counter1" // counter name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.CounterId); // counter
Debug.Log(item.Name); // counter name
Debug.Log(item.Count); // count value
Debug.Log(item.CreatedAt); // creation date and time
Debug.Log(item.UpdatedAt); // last updated date

Check the current value of the counter. Depending on this value, limit quest challenges or change the products available for purchase.

GS2-Lock

Service Overview

This service is designed to achieve exclusivity.

Resource operations by the API in GS2 are not exclusive as they are.
When increasing or decreasing a resource using a stamp sheet, this service is automatically used to acquire a lock using the ID of the target resource as a key.
When increasing or decreasing resources without going through the stamp sheet, you must explicitly use GS2-Lock to perform the lock operation.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Limit the number of operations on the same mutex to three per second.
This limit does not apply to operations on different mutexes.

Basic usage

There are three steps to use.

  1. Create a namespace
  2. Locking.
  3. Unlocking.

Create a namespace

Create the namespace from the Management Console. No special configuration is required.

Locking

Lock from client Example implementation (Unity/UniTask enabled)

var domain = gs2.Lock.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Mutex(
    propertyId: "property-0001" // property ID
);
var result = await domain.LockAsync(
    transactionId: "transaction-0001", // transaction ID to acquire lock
    ttl: 100000L // Expiration time to acquire lock (seconds)
);
var item = await result.ModelAsync();

Debug.Log(item.MutexId); // Mutex GRN
Debug.Log(item.PropertyId); // property ID
Debug.Log(item.TransactionId); // Transaction ID for which the lock was acquired

Example of locking from the client (Unity)

AsyncResult<EzLockResult> asyncResult = null;
var current = gs2.Lock.Lock(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    propertyId: "property-0001", // property ID
    transactionId: "transaction-0001", // transaction ID to acquire lock
    ttl: 100000L // time limit to acquire lock (seconds)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.MutexId); // Mutex GRN
Debug.Log(item.PropertyId); // property ID
Debug.Log(item.TransactionId); // Transaction ID for which the lock was acquired

Example of locking from the server (python)

from gs2_lock_client.request import LockByUserIdRequest
from gs2_lock_client.result import LockByUserIdResult

result = client.lock_by_user_id(
    LockByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_property_id(property_id)\
        .with_user_id(user_id)\
        .with_transaction_id(transaction_id)\
        .with_ttl(ttl)
)

It can be locked from the client and server, respectively.
Since it is used for editing properties directly, it is rather used from the server.
If you run it from the client and the client crashes before you can lock and unlock it, you can use the
The property will remain locked for a long time, causing a bug.

Unlocking

Unlock from client Example implementation (Unity/UniTask enabled)

var domain = gs2.Lock.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Mutex(
    propertyId: "property-0001" // property ID
);
var result = await domain.UnlockAsync(
    transactionId: "transaction-0001" // Transaction ID for which the lock was acquired
);
var item = await result.ModelAsync();

Debug.Log(item.MutexId); // Mutex GRN
Debug.Log(item.PropertyId); // property ID
Debug.Log(item.TransactionId); // Transaction ID for which the lock was acquired

Unlock from client Example implementation (Unity)

AsyncResult<EzUnlockResult> asyncResult = null;
var current = gs2.Lock.Unlock(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    propertyId: "property-0001", // property ID
    transactionId: "transaction-0001" // transaction ID for which the lock was acquired
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.MutexId); // Mutex GRN
Debug.Log(item.PropertyId); // property ID
Debug.Log(item.TransactionId); // Transaction ID for which the lock was acquired

Example of unlocking from server (python)


from gs2_lock_client.request import LockByUserIdRequest
from gs2_lock_client.result import LockByUserIdResult

result = client.lock_by_user_id(
    LockByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_property_id(property_id)\
        .with_user_id(user_id)\
        .with_transaction_id(transaction_id)\
        .with_ttl(ttl)
)

GS2-Log

Service Overview

This service is designed to realize the aggregation and compilation of logs.

This service enables searching and aggregation of access logs to GS2 and resource exchange logs using stamp sheets.
Three types of log storage locations are available.

To configure which microservice logs are aggregated, set the GS2-Logs namespace to the namespace setting for each service.
If you use GS2 Log Storage / Google BigQuery Log Storage, you can set the log storage period.

Pricing

General usage

0.02 yen per API request

Service-specific

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Create a namespace
  2. Configure logging settings from the namespace of the service for which you want to log.

Create a namespace

Create it in the Management Console. You will need to specify the log export method (storage method).

Configure log output settings in the namespace information of the service for which you want to retrieve log output

For example, if you want to configure log output for GS2-Account
From the Management Console, go to namespace information, then to namespace update, and then to log output settings.
Select the GS2-Log namespace in Log Output Settings to save logs of API calls for GS2-Account.
If there are multiple GS2-Account namespaces, you will need to set each of them.

If you create multiple GS2-Log namespaces, you can have separate log destinations for each namespace for each service.
In addition to simply separating logs for each service, you can also consider separating log output for each person in charge when multiple people are managing the system.

.

GS2-Lottery

Service Overview

This service realizes the lottery process.

Lottery processing is based on an ejection probability table. The ejection probability table is used to set the weight of each prize to be ejected.
For example, if you set 3 for prize A and 1 for prize B, the ejection probability of prize A is 75% and that of prize B is 25%.

You can also set other emission probability tables as prizes.
By preparing tables for each rarity (SSR, SR, R, etc.) in advance, and then creating a table for each of these rarities as prizes, it is easy to set the emission probability for each rarity.

There are two modes of lottery processing, which can be set in the lottery model.
The first is a mode in which the lottery is processed uniformly with the same probability each time, and the second is a box-gacha mode.
In the box gacha mode, a prize is removed from the box each time the lottery is processed, and all the prizes are obtained when the same number of times as the number of prizes initially placed in the box is drawn.
When Box Gacha is set as the mode, the lottery begins with the number of prizes in the box equal to the number of weights set in the ejection table.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Create emission establishment table
  2. Execute the lottery process

Create a master

First, create an emission probability table master. Define the likelihood of each prize to be discharged.

The discharge probability is set by the 'weight'. For example, if prize A has a weight of 1 and prize B has a weight of 3, prize A will be discharged at 1/(1+3)=25% and prize B at 75%.
In addition, a prize can be assigned an ejection probability table, which can be structured as a tree.

For example, set the weights of rare items 1-2 to "Rare" and normal items 1-7 to "Normal" to 1 in the emission probability table "Rare".
Then, for the "Gacha" table, the "Rare" table is set to a weight of 1 and the "Normal" table is set to a weight of 7.
In this case, the probability of receiving a rare item 1 is (1/8) (1/2)=6.25% and the probability of receiving a normal item 1 is (7/8) (1/7)=12.5%.

Next, create a lottery type master.

First, set the lottery mode. In the normal lottery, prizes are always ejected at a predetermined rate; in the BOX lottery, once ejected, the prize is no longer ejected.

Next, set the lottery method. If you wish to use the emission probability table you created earlier, select the static lottery table. Then, specify the emission probability table you created.

If the dynamic lottery table by GS2-Script is selected as the lottery method, the probability can be varied according to the state using GS2-Script.
Please check GS2-Script.

Execute the lottery process

ApplicationAccess, the security policy for users, does not allow the client to directly call the API that handles the lottery.
This is to prevent cheaters from illegally executing the lottery process.

When a client requests a lottery process, it is assumed that it will work with other services.
For example, open the GS2-Exchange exchange rate master in the Management Console.
In the Get Action List => List of types of actions to perform on the stamp sheet you will find 'Lottery: perform lottery'.
GS2-Exchange is a function that allows you to exchange resources. If you specify in-game currency or gacha tickets in the Consume action, you can realize a function that spends in-game currency or tickets to run a gacha.
Another use is to link with GS2-Quest to draw items for stage clear rewards.

GS2-Matchmaking

Service Overview

This service realizes opponents and cooperative partners.

The matchmaking process is as follows

Host creates a gathering

Participants search for a gathering that meets their criteria.

Matchmaking is complete when the specified number of people have been reached.

GS2-Matchmaking is designed to meet as many of these needs as possible regarding `participant search for matching gatherings.
Here is an example of the design with use cases.

There are two game modes in the game, one for casual players and the other for core gamers.
Suppose we want to perform the matchmaking process without mixing these players.

You can specify up to five attribute values when creating a gathering or when searching for a gathering.
When creating a gathering, you can specify a range of attribute values for the players to be recruited, and
When searching for a gathering, the request for processing is made by specifying the value of its own attribute value.

In other words, when the host creates a gathering, he/she specifies the game mode to be recruited in the attribute value 1, and when he/she searches for a gathering, he/she specifies his/her own attribute value.
By specifying the game mode that the searcher wishes to participate in as attribute value 1, players with the same desired game mode will be matched with each other.

The host specifies the minimum and maximum levels to be recruited in attribute value 2 when creating the gathering.
The searcher can specify his/her own level in attribute value 2 to matchmaking with other players in the same level range.

If multiple attribute values are specified, the search will be processed to find a match that meets the range of all attribute values.

Suppose you start out recruiting within a narrow range and try to make matches between players of the same level, but if you have trouble finding opponents, you want to expand the range of levels in which you can recruit.
There is a GS2-Script event that fires approximately every minute after the Gathering is created.
This script can be used to gradually relax the desired conditions by relaxing the range of the Gathering's attribute values.

An option when creating a gathering is to specify a list of user IDs that are allowed to participate.
This can be used to limit the number of participants by specifying a list of friends' user IDs.

You can specify a blacklist of user IDs when creating or searching for a Gathering.
The blacklist specified at search time will discover Gatherings that match the criteria and will be added to the blacklist of Gatherings in which you have participated.
If you are on the blacklist when searching, you will be excluded from matchmaking.

In some games, you may want to make a matchmaking with one shield, one healer, and two attackers.
The role attribute can be used in this case.

Assume a tank as a shield, a healer as a healer, and an attacker as an attacker.
When you create a gathering, you set the number of recruits for each role.
By setting this for your role when searching for a gathering, only those gatherings that have openings for that role will be treated as open gatherings.

You can also set an alias for the recruiting role.
For example, tank could be represented by a more specific role, and the search for a gathering could be performed as either paladin, warrior, or dark_knight.
When creating a gathering, if you specify paladin and dark_knight as aliases for tank, you can create a gathering in which warrior cannot participate.

Used when one player leaves the matchmaking process and only one player needs to be replaced after the match is completed.
The party token is used in this case. To issue a party token, you must have the player token of the player who is organizing the party.
Player tokens are tokens that allow the player himself to allow a party representative to perform matchmaking on his behalf, and they have a three-minute validity period.
Each party member obtains a player token by making a request to the API that issues player tokens and sends it to the party representative.
The party representative receives the player token from the party member and sends it to the party token issuing API within 3 minutes to obtain a party token.
The party token has a validity period of 10 minutes, and the party token is used to call the gathering creation process or the gathering search process within 10 minutes.
In this way, you can create a gathering with all party members participating or join a gathering in which all party members can participate.

In a 4 vs. 4 game, you may want to play against a prearranged party without dispersing the party to the opposing side.
For example, you may want to matchmake a prearranged party of 3 players, a prearranged party of 4 players, and one stray player to
Suppose you want to realize a match party of 3 players + 1 stray player vs party of 4 players in advance.
In such a case, we first execute the matchmaking for the 4 players.
Then you will have two gatherings: a party of 3 players + 1 stray player and a party of 4 players organized in advance.
Then, a representative from each party performs matchmaking with a capacity of 2 players, and the parties are matched against each other.
In this way, you can have a pre-arranged party of 3 players + 1 stray player vs. a pre-arranged party of 4 players.

It may be necessary for players to communicate with each other without matchmaking being completed.
GS2-Matchmaking provides two means of communication between players during the creation of a gathering.

If you want to exchange metadata between players at a low frequency, even when recruitment is not finished, you can use the former method, and if you want to exchange metadata between players at a high frequency, you can use the latter method.
Use the latter if you want to have the game played with NPCs or with insufficient numbers of players while recruiting.

GS2-Chat's limitations can be used as a criterion for determining low or high frequency.
GS2-Chat allows only 3 comments per second per chat room. If this frequency is exceeded, GS2-Realtime should be used.

When matchmaking is completed, you can notify players of the completion of matchmaking by in-game push notification usingGS2-Gatewayorjob registration using GS2-JobQueue.
You can also run arbitrary scripts using GS2-Script'. If you want to use GS2-Realtime to realize competitive or cooperative play after matchmaking, you can use GS2-Script, which is executed after matchmaking is completed, to You can create a GS2-Realtime gathering and direct it to the game server by notifying the gathering's IP address and port information usingGS2-Gateway in-game push notificationorGS2-JobQueue job registration`.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

To realize a multiplayer game, a mechanism is needed to find opponents and cooperative players.
GS2 offers GS2-Matchmaking as a service to help you achieve this.

In general, two approaches to matchmaking exist.

GS2 offers only the latter, automatic matchmaking.
Manual matchmaking has the advantage of finding rooms that better meet the needs of game players, but there is a time lag between the listing and the join action, which is caused by the human selection process. This is because there are not many use cases where people want to search for opponents strictly enough to require manual matchmaking, while the UX design is very difficult because it is easy to end up in a situation where a room is full when you try to join it.

Gathering

GS2-Matchmaking brings together game players with compatible matchmaking conditions to create a gathering.
A gathering can be thought of as a room.
The host player creates the Gathering first, and guests are assigned to matching Gatherings.
When the number of players in a Gathering reaches a certain number, a notification is sent and a script is executed to confirm that the matchmaking is successful, and the Gathering is then deleted.

Setting Conditions

Attribute value

Up to five attribute values can be specified for matchmaking conditions.
Attribute values are integer values, with a minimum and maximum value. When looking for opponents, we look for game players who have all attribute values within the desired range.

Role

It is used to achieve role-based matchmaking.
Roles are categorized as shield, healer, attacker, etc. Matchmaking conditions can be specified in the form of 1 shield, 1 healer, 2 attackers, etc.

Role alias

Roles can have aliases.
For example, suppose that the role is Shield, but the in-game professions are Warrior and Knight.
You want your opponent to be a Warrior, but you don't want him to be a Knight. In this case, an alias can be used.

Instead of directly declaring your role as a shield, you should declare your role as a warrior knight, and in general matchmaking, the alias for the shield role should be set to warrior knight.
This will create a Gathering in which both Warrior and Knight can participate as Shields.
If you do not want only Warriors to participate in matchmaking, you can include only Warriors in the alias.
Then the Knight will not be recognized as a shield and will be excluded from the matchmaking.

Loosen matchmaking conditions

The more exacting the conditions, the better the quality matchmaking.
For example, if the rating is set as a matchmaking condition, the more the rating values are exactly the same, the better the matchmaking.
On the other hand, good matchmaking requires a large number of game players. On the other hand, good matchmaking requires a large number of players, because no two players have such a conveniently close match of skills.

That said, there is no need to give up on quality matchmaking from the outset, and a wide range of ratings to be used as matchmaking conditions.

GS2-Matchmaking allows a script to run every minute from the start of the gathering.
This feature allows you to relax matchmaking conditions according to the waiting time.
This allows you to design good quality matchmaking if you have a partner, and if not, to find an opponent anyway.

Gathering open to friends only

Gatherings can be restricted to participants by enumerating the user IDs that can participate.
This feature allows for matchmaking in which only friends can participate.

Blacklist

GS2-Matchmaking has a blacklist feature.
Game players whose user IDs are included in the blacklist will not be able to participate in the gathering, even if they meet the matchmaking requirements.
The blacklist information can be held by each player, and the merged blacklist of all players in the Gathering will be used as the Gathering's blacklist.

Party and player tokens

Party tokens can be used to allow multiple players to participate in a single gathering together.
Party Tokens allow multiple players to create a Gathering together and participate in the same Gathering together.

Party tokens are created by a party representative who collects player tokens from each player in the party.
Player tokens expire in 3 minutes and party tokens expire in 10 minutes.

Additional Recruitment

Once matchmaking has been completed, one person may leave the group for some reason and the group may wish to recruit again.
In such a case, a party token can be created with the remaining members, and the matchmaking can be performed again to recruit additional members to fill the vacancy.

Matchmaking between parties

Depending on the game specifications, you may wish to have team competitions, such as 4vs4.
In such cases, there may be specifications where you want to team up friends with each other.
To achieve such a specification using GS2-Matchmaking, once a 4-player matchmaking is executed to create a team.
In this case, teams of friends are created through friends-only matchmaking.
Then, each team would be designed so that a representative from each team would run a 2-person matchmaking to discover a gatherer to be the 4vs4 opponent.

Player-to-player communication during matchmaking

Sometimes you want to do messaging between players even when matchmaking is not finished.
The GS2-Chat / GS2-Realtime linkage can be used in such cases.
With this function, a GS2-Chat or GS2-Realtime room can be created when a gathering is created or matchmaking is completed.
In this case, by creating a room at the time of gathering creation, it can be used for messaging during matchmaking.

There are several indicators to determine whether GS2-Chat or GS2-Realtime should be used, but if GS2-Realtime is to be used for matchmaking matches after matchmaking is complete, then using GS2-Realtime for communication during matchmaking is Implementation will be less time-consuming.
Another indicator is the communication interval; GS2-Chat has a limit of three messages per second per room, so if you need to communicate more frequently than this, you should use GS2-Realtime.
The last indicator is cost: GS2-Chat charges by the number of API requests, while GS2-Realtime charges per minute of room maintenance time plus network traffic, and does not charge for the number of API requests.

Please consider which method is best for your game to achieve the specifications using this area as material.

Matchmaking progress handling

GS2-Realtime is able to handle matchmaking progress via GS2-Gateway push notifications.
The following types of notifications are available

When matchmaking is completed, in addition to notification by GS2-Gateway, handling using GS2-JobQueue and handling using GS2-Script are also supported.

Using the GS2-Realtime integration, a room creation request is automatically issued when a gathering is created or a matchmaking session is completed, and the GS2-Gateway will notify you when the room creation is complete.
The notification will include the IP address of the activated game server and the port to listen on. The notification includes information such as the IP address and standby port of the activated game server and the encryption key used to encrypt communication packets, which can then be used to take over the game.

Creating Gatherings

Creating a Gathering Example Implementation (with Unity/UniTask enabled)

var domain = gs2.Matchmaking.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var result = await domain.CreateGatheringAsync(
    player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer()
        .WithAttributes(new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute_[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute_()
            .WithName("stage")
            .WithValue(1),
    new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute_()
            .WithName("level")
            .WithValue(10)
    }), // Own player information
    attributeRanges: new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
            .WithName("stage")
            .WithMin(1)
            .WithMax(1),
    new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
            .WithName("level")
            .WithMin(0)
            .WithMax(10)
    }, // application limit
    capacityOfRoles: new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole()
            .WithRoleName("default")
            .WithCapacity(4)
    }, // application Requirements (Optional)
    allowUserIds: null, // list of user IDs allowed to participate (optional)
    expiresAt: null, // Gathering expiration date (optional)
    expiresAtTimeSpan: null // time to expiration (optional)
);
var item = await result.ModelAsync();

Debug.Log(item.GatheringId); // gathering GRN
Debug.Log(item.Name); // gathering name
Debug.Log(item.AttributeRanges); // recruitment conditions
Debug.Log(item.CapacityOfRoles); // Participants
Debug.Log(item.AllowUserIds); // List of user IDs allowed to participate
Debug.Log(item.Metadata); // metadata
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated

Creating a Gathering Example Implementation (Unity)

AsyncResult<EzCreateGatheringResult> asyncResult = null;
var current = gs2.Matchmaking.CreateGathering(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer()
        .WithAttributes(new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute_[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute()
            .WithName("stage")
            .WithValue(1),
    new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute()
            .WithName("level")
            .WithValue(10)
    }), // Own player information
    capacityOfRoles: new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole()
            .WithRoleName("default")
            .WithCapacity(4)
    }, // application limit
    attributeRanges: new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange[] {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
            .WithName("stage")
            .WithMin(1)
            .WithMax(1),
    new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
            .WithName("level")
            .WithMin(0)
            .WithMax(10)
    }, // Application Requirements (Optional)
    allowUserIds: null, // list of user IDs allowed to participate (optional)
    expiresAt: null, // Gathering expiration date (optional)
    expiresAtTimeSpan: null // time to expiration (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.GatheringId); // gathering GRN
Debug.Log(item.Name); // gathering name
Debug.Log(item.AttributeRanges); // Recruitment conditions
Debug.Log(item.CapacityOfRoles); // Participants
Debug.Log(item.AllowUserIds); // List of user IDs allowed to participate
Debug.Log(item.Metadata); // metadata
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated

To create a Gathering, you need to set the recruitment criteria and the list of available user IDs.
There are two types of recruitment conditions: attribute values and the number of participants.

Attribute value

Attribute Value Model Structure

Parameter Data type Mandatory Description
name string true Attribute name
min integer true Minimum value of the attribute value that can participate in the gathering
max integer true Maximum value of the attribute value that can participate in the gathering

Specify up to five attribute values. Attribute values can be specified in a range of integer values.
When a game player submits a matchmaking request, he/she declares the value of his/her attribute values, and the gatherings that fall within the attribute value range are determined as candidate gatherings for participation.

Terms and Conditions of Application

Application Conditions Model Structure

Parameter Data type Mandatory Description
roleName string true Role name
roleAliases list[string] false Alias list of role names
capacity integer true Number of applicants
participants list[Player] true List of participants' player information

The number of recruits is literally a parameter for how many game players you will find.
The number of recruits can be set for each role.
A role can be defined as 1 shield, 1 healer, 2 attackers, and so on.
If you are not picky, you can specify only one role and fill it with the number of recruits to create a gathering.

Performing Matchmaking

The participant finds a Gathering in which he/she can participate and joins it.
The Matchmaking API responds with a context token if it does not find any available gatherings after a certain period of time, and if it has not finished scanning all the gatherings.
The context token is a string of information needed to restart the matchmaking process.
If the process runs to the end but fails to find a gatherer to join, null is returned, and the gatherer's creation process should be performed with that response.

Matchmaking Request Implementation Example (Unity/UniTask enabled)

var domain = gs2.Matchmaking.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var items = await domain.DoMatchmakingAsync(
).ToListAsync();

var item = result.Item;

Debug.Log(item.GatheringId); // gathering GRN
Debug.Log(item.Name); // gathering name
Debug.Log(item.AttributeRanges); // Recruitment conditions
Debug.Log(item.CapacityOfRoles); // Participants
Debug.Log(item.AllowUserIds); // List of user IDs allowed to participate
Debug.Log(item.Metadata); // metadata
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated

Matchmaking Request Example (Unity)

AsyncResult<EzDoMatchmakingResult> asyncResult = null;
var current = gs2.Matchmaking.DoMatchmaking(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    player: {'userId': 'user-0001', 'attributes': [{'name': 'attr1', 'value': 1}, {'name': 'attr2', 'value': 1}]}, // own player information
    matchmakingContextToken: null // token to hold matchmaking state used to resume search (optional value)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var matchmakingContextToken = result.MatchmakingContextToken;

Debug.Log(item.GatheringId); // gathering GRN
Debug.Log(item.Name); // gathering name
Debug.Log(item.AttributeRanges); // Recruitment conditions
Debug.Log(item.CapacityOfRoles); // Participants
Debug.Log(item.AllowUserIds); // List of user IDs allowed to participate
Debug.Log(item.Metadata); // metadata
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated
Debug.Log(matchmakingContextToken); // token that holds the matchmaking status

Matchmaking Interruption

Used when you have already joined one of the Gatherings and wish to leave the Gathering.

Matchmaking Cancel Implementation Example (Unity/UniTask enabled)

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace1" // namespace name
    ).Me(
        gameSession: gameSession // GameSession object (access token)
    ).Gathering(
        gatheringName: "$gathering1.name" // gathering name
    );
    var result = await domain.CancelMatchmakingAsync(
    );
    var item = await result.ModelAsync();

Matchmaking Cancel Implementation Example (Unity)

AsyncResult<EzCancelMatchmakingResult> asyncResult = null;
var current = gs2.Matchmaking.CancelMatchmaking(
callback: r => { asyncResult = r; },
session: session, // GameSession object (access token)
namespaceName: "namespace1", // namespace name
gatheringName: "gathering1-name" // gathering name );

yield return current; if (asyncResult.Error != null) {
OnError(asyncResult.Error);
yield break; }

var result = asyncResult.Result; var item = result.Item;

Debug.Log(item.GatheringId); // gathering GRN Debug.Log(item.Name); // gathering name Debug.Log(item.AttributeRanges); // Recruitment conditions Debug.Log(item.CapacityOfRoles); // Participants Debug.Log(item.AllowUserIds); // List of user IDs allowed to participate Debug.Log(item.Metadata); // metadata Debug.Log(item.CreatedAt); // Creation date and time Debug.Log(item.UpdatedAt); // Last updated

Rating

You can use the ratings provided by GS2-Macthmaking for the Gathering attribute values to achieve matching in the same level range.
The use of ratings requires that the ratings be calculated based on unadulterated win/loss results.
If the game server can determine the win or loss, the game server can report the win or loss.
GS2Realtime will also be able to report win/loss results.
On the other hand, when the client reports the win/loss result, such as in P2P games, it is necessary to prevent cheaters from falsifying the win/loss result.
Therefore, GS2Macthmaking provides a way for clients to vote for the winners.

Ballots and Voting

Clients participating in the match will vote for a ballot and each player's win/loss/ranking.
GS2-Macthmaking determines the winner and rank by majority vote and calculates the rating.
In this way, each client can vote separately to GS2Macthmaking, but the client cannot know when the votes are collected and the ratings are calculated.
Therefore, one of the winning clients is designated as the representative, and each client's ballot is collected by the representative client, and
We recommend that the representative client notifies each client of the result by sending a ballot to GS2-Macthmaking when the majority of the ballots have been received.
The reason we use the term "winning client" is that there is an incentive for the losing client to report that they won, but not vice versa.
It is possible that the losing side will not hand in their ballots, but even in that case, if there is a majority of ballots, the results can still be passed.

Possibility that the vote will not be approved

Although we have introduced the method of voting on win/loss results as an anti-cheating measure, it is not possible to completely eliminate cheating.
For example, in the case of a one-on-one game, if one player reports a false win or loss, it is impossible to determine the correct winner.
As the number of players increases, so does the credibility of the system, but the possibility of incorrect voting cannot be completely eliminated.
If the number of players is small, or if you want to completely prevent cheating, consider building a game server.

GS2-Mission

Service Overview

This service provides a mission function.

The mission function allows users to set conditions such as "complete n quests" or "obtain n characters" and receive rewards for achieving these conditions.
To achieve this, a mechanism called "setting mission conditions," "subscribing to a counter," and "raising the counter" is used.

Setting a condition for a mission is to set a counter threshold at which the mission will have been accomplished.

Subscribing to a counter is the setting of the counter to which the mission is subject.
One counter can be subscribed to from multiple missions, and different reset timings can be set for each mission.
For example, if you want to create a mission that says "completed a total of 1000 quests" and a daily mission that says "completed 10 quests today
Subscribe to one counter from both missions that counts up each time a quest is completed, 'no reset' for the former and
By setting a 'daily' reset timing, you can handle missions with multiple conditions with a single counter operation.

Raise Counter is an operation that literally raises the counter, for example, when a quest is completed, the counter rise in the number of times the quest is completed is included in the reward.

Two durations can be set for a mission.
The first is the period during which the counter can be manipulated, and is used in cases where raising the counter is limited to the event period.
The second is the period during which mission rewards can be received, and can be used to set two separate periods when you want to receive only mission rewards for a while after the event is over.
To specify the time period, associate the event with the GS2-Schedule event.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Please limit the number of operations on the same counter to 3 operations per second.
This limit does not apply to operations on different counters by different users or even by the same user.

Basic usage

There are three steps to use.

  1. Creating a Master data
  2. Counter increase
  3. Receive mission rewards

Creating a Master data

Create in the Management Console.
The masters to be created are 'counters', 'mission groups', and 'tasks' to be set within 'mission groups'.

Counter

This counter is used to determine if a mission has been accomplished.
For example, if the mission is to fight 10 times, the number of fights will be counted up when the fight is completed.
The counter can be reset periodically (daily, weekly, monthly).
Please set this when you want to realize daily missions, etc.

It is also possible to create a counter that can count up only during the event in conjunction with GS2-Schedule.
Please check the GS2-Schedule page.

Mission group

A mission group serves to unite individual missions.
Mission Groups can be assigned a reset timing for missions.
For example, you can create a Daily Mission Group, Weekly Mission Group, and Indefinite Mission Group by reset timing, and register missions in each Mission Group for easy management.

Task

In GS2, individual missions are called tasks. They are registered in the mission group.
At this time, the counter created as a condition for accomplishing the task and the target value of that counter are set.
Next, the reward is set. This reward can also increase any counter, for example, you can create a task to accomplish three daily missions.

Counter increase

The API for increasing the counter cannot be executed from the client with ApplicationAccess, which is the security policy for users.
This is to prevent cheating to increase the counter illegally.

There are three ways to increase counters.

Set up as a stamp sheet reward

For example, open the Quest Model Master of GS2-Quest in the Management Console.
In it, you will find "Mission: Add to Counter" as a reward for completing a quest.
In this case, you can use it as a way to increase the quest clear count counter.
You can also add to the counter from other services, so please find a suitable method.

Increase with GS2-Script

There may be other ways to increase the counter other than by rewarding GS2 events. An example is a login counter.
In this case, you can write a GS2-Script that increases the counter and set it to run on login in the GS2-Acount namespace.
Please also check GS2-Script.

Calling the API from the server

Example of increasing a counter from a server (Python)

from gs2_mission_client.request import IncreaseCounterByUserIdRequest
from gs2_mission_client.result import IncreaseCounterByUserIdResult

result = client.increase_counter_by_user_id(
    IncreaseCounterByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_counter_name(counter_name)\
        .with_user_id(user_id)\
        .with_value(value)
)

You can also call the API from your own server to increase the counter.

Receive mission rewards

Receive mission rewards Example implementation (Unity/UniTask enabled)

var domain = gs2.Mission.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Complete(
    missionGroupName: "mission-group-0001" // mission group name
);
var result = await domain.ReceiveRewardsAsync(
    missionTaskName: "mission-task-0001" // task name
);

var result = asyncResult.Result;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(stampSheet); // Stamp sheet to receive rewards for mission accomplishment
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Receive mission rewards Implementation example (Unity)

AsyncResult<EzReceiveRewardsResult> asyncResult = null;
var current = gs2.Mission.ReceiveRewards(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    missionGroupName: "mission-group-0001", // mission group name
    missionTaskName: "mission-task-0001" // task name
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(stampSheet); // Stamp sheet to receive rewards for mission accomplishment
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Once the mission is accomplished, the mission accomplishment reward is obtained.
It is important to note that obtaining the mission accomplishment reward alone does not reward you.
If there is only one reward for a mission, you need to execute a stamp sheet, and if there are two or more rewards, you need to use GS2-JobQueue.
For more information on Stamp Sheets, please refer to the Stamp Sheet page.
For information on GS2-JobQueue, please refer to the GS2-JobQueue page.

GS2-Money

Service Overview

This service manages billable currency.

Billing currency refers to in-game currency that falls under the category of prepaid means of payment (home-grown) as defined by Japan's Funds Settlement Law.
To comply with the Funds Settlement Act, GS2-Money manages balances and currency transactions.

If you do not wish to share your wallet between different platforms, we also provide a mechanism to separate wallets within the same account depending on the platform from which you are accessing it.
Even in that case, the free offering can be shared between different platforms.

Pricing

General usage

0.02 yen per API request

Service-specific

In addition to the regular API usage fee, a revenue share of the distribution amount will be applied.

Range of monthly distribution amount Revenue
¥0 - ¥999,999 10%
¥1,000,000 - ¥9,999,999 5%
¥10,000,000 - ¥99,999,999 3%
¥100,000,000 - ¥999,999,999 1%
¥1,000,000,000 to ¥100,000,000,000 0%.

The usual free quota does not apply to revenue sharing, with the exception that if the monthly circulation is less than 10,000 yen, no fee will be charged.

Restrictions and limitations

Please limit the number of operations on the same wallet to three per second.
This limit does not apply to operations on different users or on different wallets of the same user.

Basic usage

There are roughly three different ways to monetize games.

Of these, GS2-Money provides the functionality to realize monetization through in-app purchases.
GS2-Money has all the necessary functions to handle in-game currency.

What is billable currency?

Billing currency refers to in-game currency that can be purchased with cash.
Currency purchased with cash is subject to the restrictions of the Funds Settlement Law in Japan, commonly known as the Funds Settlement Act, and must be managed in accordance with its provisions.

About the Japanese Funds Settlement Law

Under the law on electronic payments, in-game currency is generally considered a prepaid means of payment.
There are two types of prepaid means ofpayment: private and third-party.
Please consult with a legal expert to determine which method your title's in-game currency actually falls under.

GS2-Money Features

GS2-Money is designed to meet the legal requirements for "prepaid means of payment" (home-grown).
Specifically, it has the following features

GS2-Money also integrates the management of free currency. This allows users to automatically combine currency purchased for a fee with currency obtained for free when consuming currency.

Currency per unit of cash

GS2-Money maintains a unit price for cash for each currency obtained.
For example, if you acquire 100 in-game currency for 200 yen and then acquire 100 in-game currency for 100 yen, GS2-Money will not treat you as having 200 in-game currency with a unit price of 1.5 for cash, but will treat you as having 100 in-game currency with a unit price of 2 for cash and 100 in-game currency with a unit price of 1 for cash, respectively. The system will manage the money as if it were owned by the customer. Free items are treated as having a cash value of 0.
Also, when in-game currency is consumed, the system keeps track of how much of the in-game currency has been consumed and how much of the in-game currency with which unit price versus cash remains.

Currency Consumption Priority

Although GS2-Money internally manages different in-game currencies with different unit cash values, there is no need to be aware of the amount of each individual possession when consuming it.
For example, if you have 100 in-game currency with a cash unit price of 1, or 100 in-game currency with a cash unit price of 1 and 2, you can spend 100 in-game currency from there without being aware of the difference.
If you have multiple in-game currencies with different cash value, you can choose from the following policies to prioritize where to spend them.

Recording receipts

GS2-Money validates receipts for each payment platform and provides the ability to record used receipts.
The following platforms are currently supported

The following platforms will be supported soon

Obtaining Currency

Security Precautions

The acquisition of currency is an extremely sensitive operation.
Not only does it affect gameplay and the in-game economy, but it also increases the user's assets, which have a cash value and are subject to the restrictions of the Funds Settlement Act regarding their management.
Accepting arbitrary actions from the client to obtain the currency may result in the unauthorized proliferation of its cash value.

Therefore, GS2 only allows users to obtain currency by using stamp sheets as rewards.
The content of stamp sheet rewards is defined on the server, and the stamp sheet mechanism guarantees that purchases are made in the in-game store before the rewards are earned, preventing unauthorized proliferation of currency.
Therefore, the rewards should be designed in such a way that they can be obtained through in-game store purchases or as rewards for quests.

Currency Consumption

Currency consumption Implementation example (with Unity/UniTask enabled)

var domain = gs2.Money.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Wallet(
    slot: 0 // slot number
);
var result = await domain.WithdrawAsync(
    count: 50, // quantity of billable currency to consume
    paidOnly: null // whether to target paid currency only
);
var item = await result.ModelAsync();
var price = result.Price;

Debug.Log(item.Slot); // slot number
Debug.Log(item.Paid); // Paid currency amount
Debug.Log(item.Free); // Amount of unpaid currency
Debug.Log(item.UpdatedAt); // Last updated date
Debug.Log(price); // price of currency consumed

Currency Consumption Implementation Example (Unity)

AsyncResult<EzWithdrawResult> asyncResult = null;
var current = gs2.Money.Withdraw(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    slot: 0, // slot number
    count: 50, // quantity of billable currency to consume
    paidOnly: false // whether only paid currency is targeted
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var price = result.Price;

Debug.Log(item.Slot); // slot number
Debug.Log(item.Paid); // Paid currency amount
Debug.Log(item.Free); // Amount of unpaid currency
Debug.Log(item.UpdatedAt); // Last updated date
Debug.Log(price); // price of currency consumed

GS2 recommends that currency consumption be expressed as an exchange of consideration and the granting of rewards using GS2-Showcase and GS2-Exchange.
However, currency consumption can also be performed via the API so that it can be used when granting rewards that are not managed by the server.

Secondary Currency Management

GS2-Money also supports the handling of secondary currencies.
Secondary currency refers to items obtained in exchange for currency, and depending on the interpretation of the Funds Settlement Law, these may be required to be treated in the same manner as currency obtained in exchange for direct cash.
For example, if a stamina drink is purchased with ¥100 worth of billable currency, the stamina drink is also considered to be billable currency with an inherited value of ¥100.
In GS2, if a GS2-Money currency (in-game currency in the above example) is set as the consideration in GS2-Showcase or GS2-Exchange and a GS2-Money currency (Stamina drink in the above example) is also set as the reward, the value of the Stamina drink can be considered to be inherited across different types of currencies. The system is designed to take over.

TIPS

Purchase billable currency with cash

Enable monthly subscriptions

What we must do as a business

Once the unspent balance of in-game currency exceeds 10 million yen as of March 31/September 30, the relevant in-game currency becomes subject to the Funds Settlement Law.
In doing so, not only GS2, but also the operator using GS2 will be subject to a certain level of liability.
Please consult with a specialist for details on what kind of liability will be incurred, but the following is a representative list.

Compliance
user protection

GS2's services are provided using Amazon Web Services and Google Cloud Platform.
These providers are ISO 27001 (security), ISO 27018 (privacy), and other certifications and are properly operated.
The operators are responsible for the protection of data obtained from GS2's management console and APIs.

Complaint Handling System
business administration

GS2-News

Service Overview

This service enables the notification function.

The article data to be distributed in the announcement must be created by Hugo (https://gohugo.io/).
Upload a set of Hugo site data compressed by zip to GS2-News, or specify a repository on GitHub to reflect the data.
The entire site data must be within 100MB.

GS2-News scans /content/{sectionName}/{contentName}/index.html from the received site data.
It analyzes the Front Matter of index.* and extracts information such as the publication period. Therefore, the tree structure of the site data must follow this format
Front Matter described at the top of the content must be written in yaml format.

Front Matter can contain several control syntaxes for GS2.
If you define the content publishing conditions in the control syntax of Front Matter, GS2-News will delete the content that does not meet the publishing conditions and build the site.
GS2-News pre-builds all patterns of public/private status of content with publishing conditions set, and places them on the web server.
Therefore, if there are many contents with public conditions set, a combination explosion will occur, increasing the time and cost required for updating.
Please try to minimize the number of contents with publish conditions set.

The number of patterns for which builds are performed can be found in the return value of the site data upload.

Multiple methods are provided for clients to retrieve the site data currently available to them.

The "-D, --buildDrafts" option is not used to build the site.
Content declared as draft in Front Matter will not be delivered, even if it is present in the site data.

Control syntax for Front Matter

Setting the publication period

x_gs2_scheduleEventId: ${GS2-Schedule's event GRN}

the content will only be published during the period of the event in question.
This can be used to distribute content linked to an event.

The GRN can also use {region} and {ownerId} placeholders, which will be replaced by the running region owner ID, respectively.

grn:gs2:{region}:{ownerId}:schedule:schedule-0001:event:event-0001

Pricing

General usage

0.02 yen per API request

Service-specific

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Create an article
  2. Browse Articles

Create an article

The following links provide samples and explanations.

GitHub:gs2-news-sample

The created articles are registered through the Management Console.

It is a good idea to register the sample from the management console and try to access it in step 2 before actually starting to create it.

Browse Articles

Example of obtaining article URL (Unity)

yield return gs2.News.GetContentsUrl(
    r => {
        if (r.Error != null)
        {
            // Reached when an error occurs
            // r.Error contains the exception object that occurred
        }
        else
        {
            Debug.Log(r.Result.Items); // list[SetCookieRequestEntry] list of cookies that need to be set to access the announcement content
            Debug.Log(r.Result.BrowserUrl); // string URL to access notification content
            Debug.Log(r.Result.ZipUrl); // string URL to access the contents of the announcement in ZIP format Cookie setting is not required
        }
    },
    gameSession,    // GameSession Session object representing login state
    namespaceName,   // Namespace Name
);

You can get the URL of the currently viewable announcement article with the sample code. Access this URL to view the article.

When accessing the URL, use the cookie that needs to be set in order to access it.
This is not necessary when accessing the contents of notices in ZIP format.

GS2-Quest

Service Overview

Manage the progress of quests.

Quests can be assigned a price to start, a reward for a successful quest, or a reward for a failed quest.

The price required to start a quest can be set to consume stamina, increase the counter for a limited number of times, etc.

You can set multiple rewards for successful quests, and you can set the probability to be used when drawing lots at the start of the quest.
This can be used to separate out content that is the same as a quest but has regular content and content with rare enemies.
Rewards for successful quests can be set to character experience, items, in-game currency, etc.

Rewards for failed quests are set to return the compensation received at the start of the quest when the quest fails, for example.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

A quest is a feature that enables story progression and rewarded tasks in a game, and GS2 provides GS2-Quest to achieve this functionality.

Specifically, GS2-Quest provides the following assurances

GS2-Quest is not concerned with the following

Register a Quest Model

GS2-Quest manages quest content settings on the server side.
Therefore, you need to upload your master data to GS2-Quest in advance to use this feature.

Please refer to the following document for information on Quest's master data configuration items (what features GS2-Quest has).

Prerequisite Quests

Game specifications often require sequential access to quests.
For example, one must have completed chapter 1 in order to play chapter 2.

Thus, a quest that must be completed in advance in order to begin is called a prerequisite quest.
In GS2, a prerequisite quest can be set for each quest, so that a quest cannot be started unless the prerequisite quest is flagged as cleared.

Quest Challenge Consideration

You can set a price to be paid for attempting a quest.
For example, you can set the price to be stamina or a quest challenge item, and you can prevent quests from starting if you don't have enough of these items.

Quest Rewards

Two main types of rewards can be set for quests.

Clear rewards are literally rewards for completing a quest.
Failure rewards are rewards earned when a quest is failed, and are generally used as a function of refunding the stamina used for the challenge.

Randomization of clear rewards

The same clear rewards may be a little tasteless.
GS2-Quest allows you to set multiple rewards and have them selected at random.
As with GS2-Lottery, the probability can be set based on the weight of the reward.

Quest reward data also comes with an area for storing metadata.
For example, the metadata for clear rewards can include monster appearance patterns, so that monsters can be set to appear according to their clear rewards.

Start Quest

Example of starting a quest (Unity/UniTask enabled)

var domain = gs2.Quest.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var result = await domain.StartAsync(
    questGroupName: "group-0001", // quest group name
    questName: "quest-0001", // Quest model name
    force: null, // if a quest has already started, whether to discard it and start it (optional)
    config: null // config values to be applied to stamp sheet variables (optional)
);

var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(stampSheet); // Stamp sheet used to execute the request initiation process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Example of starting a quest (Unity)

AsyncResult<EzStartResult> asyncResult = null;
var current = gs2.Quest.Start(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    questGroupName: "group-0001", // quest group name
    questName: "quest-0001", // Quest model name
    force: null, // if a quest has already started, whether to discard it and start it (optional)
    config: null // config values to be applied to stamp sheet variables (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(stampSheet); // Stamp sheet used to execute the request initiation process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

When a quest is started, a lottery is drawn internally from the multiple registered quest rewards to determine the content of the reward.
In other words, when using GS2-Quest, the reward for completing a quest is determined at the time the quest is started.
This specification is intended to prevent fraudulent attempts to redraw the rewards by force-quitting the application after starting a quest and before completing it.

A stamp sheet will be responded to in response to the quest initiation process. The quest initiation process is held until the stamp sheet is executed.

Quest Completion

Quest Completion Example Implementation (Unity/UniTask enabled)

var domain = gs2.Quest.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Progress(
);
var result = await domain.EndAsync(
    isComplete: true, // whether the request was cleared (optional)
    rewards: new Gs2.Unity.Gs2Quest.Model.EzReward[] {
        {}
    }, // actual rewards from the quest (optional)
    config: null // optional configuration values to be applied to stamp sheet variables
);

Debug.Log(item.ProgressId); // Quest progress GRN
Debug.Log(item.TransactionId); // transaction ID
Debug.Log(item.QuestModelId); // Quest model
Debug.Log(item.RandomSeed); // random number seed
Debug.Log(item.Rewards); // Upper limit of rewards obtained from the quest
Debug.Log(stampSheet); // Stamp sheet used to execute the reward granting process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Quest Completion Example Implementation (Unity)

AsyncResult<EzEndResult> asyncResult = null;
var current = gs2.Quest.End(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    transactionId: "transaction-0001", // transaction ID
    isComplete: true, // whether the request was cleared (optional)
    rewards: new Gs2.Unity.Gs2Quest.Model.EzReward[] {
        {}
    }, // actual rewards from the quest (optional)
    config: null // optional configuration values to be applied to stamp sheet variables
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(item.ProgressId); // Quest progress GRN
Debug.Log(item.TransactionId); // transaction ID
Debug.Log(item.QuestModelId); // Quest model
Debug.Log(item.RandomSeed); // random number seed
Debug.Log(item.Rewards); // Upper limit of rewards obtained from the quest
Debug.Log(stampSheet); // Stamp sheet used to execute the reward granting process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

When you complete a quest, you can specify the reward you actually earned from the quest.
If you do not specify, you will get all the rewards that were responded to at the start of the quest. If the reward is reduced due to ignoring enemies or treasure chests in the game, report the reduced quantity here.
Attempting to get more rewards than determined at the start or attempting to get rewards that are not earned will result in an error.

By allowing the client to call quest completion, there is a possibility of cheating by reporting that the player has completed a stage of a difficulty level that is not originally clearable at the player's level.
To avoid this, the GS2-Identifier security policy can be set to prevent the client from calling Quest Completion and to call it from the server.

A stamp sheet will be responded to in response to the completion report of the quest. The quest completion process is held until the stamp sheet is executed. See the Stamp Sheet page for more information about stamp sheets.

GS2-Ranking

Service Overview

It realizes the ranking process of scores and clear times.

There are two types of ranking: global ranking, which refers to the same data for everyone, and
Scoped ranking is a ranking among friends or within a guild, where the content of the ranking is different depending on the user.

Global rankings are processed at specified intervals between 15 minutes and 24 hours.
Requests from game users are responded to with pre-tabulated results.
This is designed to ensure that response times remain the same even in the presence of a large number of game players.

Scoped ranking is a game where each game player has a score bucket, and scores are added to the score bucket as subscribed game players register their scores.
Each game player uses the scores in his or her score bucket to process the ranking.

Both Global Ranking and Scoped Ranking can be configured to hold one score per user ID or multiple scores.
You can specify whether you want only the last score registered when registering a ranking to be included in the ranking or all registered scores.
If you want all scores to be included in the ranking, the data volume will tend to grow. As a result, the GS2 usage fee will be affected.
Unless there is a major reason to do so in the game system, it is recommended to set only the last score registered to be included in the ranking.

Pricing

General usage

0.02 yen per API request

Service-specific

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are three steps to use.

  1. Create a category master
  2. Register your score
  3. View Rankings

Create a category master data

Create in the Management Console.
One thing to note in the settings section is to check the box "Only one score should be registered per user ID" unless there is a particular reason not to.
Storing multiple scores per user ID will cause the volume of data to grow and lead to increased usage fees.

Register your score

Register scores from client Example implementation (Unity/UniTask enabled)

var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Ranking(
    categoryName: "category-0001" // category name
);
var result = await domain.PutScoreAsync(
    score: 1000L, // score
    metadata: null // metadata (optional)
);
var item = await result.ModelAsync();

Debug.Log(item.CategoryName); // category name
Debug.Log(item.UserId); // user ID
Debug.Log(item.ScorerUserId); // User ID who got the score
Debug.Log(item.Score); // score
Debug.Log(item.Metadata); // metadata

Example of registration from client (Unity)

AsyncResult<EzPutScoreResult> asyncResult = null;
var current = gs2.Ranking.PutScore(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    categoryName: "category-0001", // category name
    score: 1000L, // score
    metadata: null // metadata (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;

Debug.Log(item.CategoryName); // category name
Debug.Log(item.UserId); // user ID
Debug.Log(item.ScorerUserId); // User ID who got the score
Debug.Log(item.Score); // score
Debug.Log(item.Metadata); // metadata

Example of registration from server (python)


from gs2_ranking_client.request import PutScoreByUserIdRequest
from gs2_ranking_client.result import PutScoreByUserIdResult

result = client.put_score_by_user_id(
    PutScoreByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_category_name(category_name)\
        .with_user_id(user_id)\
        .with_score(score)\
        .with_metadata(metadata)
)

Score registration can also be performed from the client in ApplicationAccess, a security policy for users.
However, when preparing rewards such as ranking rewards, there may be cheaters who register incorrect scores.
To avoid this, set the security policy so that scores cannot be registered from the client.
Please refer to the GS2-Identifier page for details on security policy settings.

You can also register scores from your own server. The safest way is to realize the game system on your own server and register the scores from the server to GS2 as a result of playing the game.

View Rankings

Get Ranking Example Implementation (Unity/UniTask enabled)

var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
);
var items = await domain.RankingsAsync(
).ToListAsync();

var items = result.Items;

Debug.Log(items); // list of rankings

Get Ranking Example Implementation (Unity)

AsyncResult<EzGetRankingResult> asyncResult = null;
var current = gs2.Ranking.GetRanking(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    categoryName: "category-0001", // category name
    limit: null, // number of data to retrieve (optional)
    accessToken: "access-token-0001", // access token
    pageToken: null, // token specifying where to start fetching data (optional)
    startIndex: 0L // index at which to start retrieving rankings (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var items = result.Items;
var nextPageToken = result.NextPageToken;

Debug.Log(items); // list of rankings
Debug.Log(nextPageToken); // page token to get the rest of the list

Get the ranking from the top.

GS2-Realtime

Service Overview

Enables competitive and cooperative play functionality.

When you create a room, three pieces of information, IP address port encryption key will be issued.
To join a room, connect to the issued IP address port via WebSocket.
The communication is done using the issued cryption key.

There is no limit to the number of simultaneous connections or frequency of communication.

Room Lifecycle

Created

GS2-Realtime starts the server after receiving a room creation request.
If the number of rooms is less than the specified number, GS2-Realtime will start additional rooms that will serve as hot standby rooms to reach the specified number.
The number of rooms is automatically adjusted by GS2.

This means that there is a difference in the time between a cold start', when the server is started after receiving a request, and ahot start', when a room on hot standby is used.

The estimated waiting time for a cold start is 40 to 60 seconds.
Estimated waiting time for a hot start is 3-5 seconds.

Exit

The activated room will be terminated if no one comes to connect for 5 minutes after it is created.
This termination process also applies to rooms on hot standby, but the hot standby startup time is not added to the usage fee.

A room will be automatically terminated after one minute of no communication from all players participating in the room.

The maximum startup time for a room is 3 hours. Rooms are automatically terminated after 3 hours of creation.

Cold Start Occurrence Conditions

Pricing

General usage

0.02 yen per API request

Service-specific

A fee is charged per minute of room startup time and for outbound data transmission capacity.
The fee for a single room remains the same whether there are 2 or 100 participants in the room.

We will make it possible to change the server specifications before the official service starts.
A high-specification server may be required when the number of players in a room is large or when communication frequency is high.

As a milestone after the official service launch, we plan to provide a function to replace the server-side implementation.
Once this feature is implemented, logic can be defined on the server side, allowing for more flexible server functionality than packet relay.
This may require a high-specification server depending on the complexity of the server-side logic.

Currently only realtime1.nano is available.

Specs Price per minute
realtime1.nano 0.04 yen
realtime1.micro 0.06 yen
realtime1.small 0.12 yen
realtime1.medium 0.24 yen
realtime1.large 0.5 yen

Data transfer capacity (outbound)

15 yen/1GB

--- (a)

If you cannot tolerate a cold start, a hot standby is available at 1500 yen per month plus tax per game server(realtime1.nano) (minimum contract: 5 game servers / minimum contract term: 1 year).
Please contact us for details.

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Tutorial

GS2-Realtime has a different interface than other SDKs.
This section describes the SDK for game engines.

Summary

GS2-Realtime uses WebSocket as its communication protocol and Protocol Buffers as the binary data format for communication.

GS2-Realtime has a profile function to synchronize data with all players and a data communication function to exchange data with other players.
RelayRealtimeSession::Send is used for data communication, and RelayRealtimeSession::UpdateProfile is used to update profiles.

In addition to these APIs, RelayRealtimeSession has the following callbacks

Callback Argument Description
OnRelayMessage RelayBinaryMessage Binaries come across when received from other players via data communication.
OnJoinPlayer Player When a new player joins a room, the information of the newly joined player is passed on. Immediately after a player joins a room, the information of the players who have already joined the room will be passed on.
OnLeavePlayer Player When a player leaves a room, the information of the departing player is passed on.
OnUpdateProfile Player Information on players who have updated their profiles will come across.
OnErrorHandler Error When an error occurs on the game server, the error message comes across.
OnGeneralErrorHandler Exception Error content comes across when an error occurs due to factors other than the game server.
OnClose Called when the connection to the game server is broken

model

Name Data type Description
connectionId uint32 Numeric-based ID randomly assigned to game players participating in the room
data bytes binary data
targetConnectionId repeated uint32 A list of data destinations. If omitted, send to everyone in the room.
Name Data type Description
connectionId uint32 Numeric-based ID randomly assigned to game players participating in the room
userId string User ID of the access token holder used at login
profile bytes Profile Data
Name Data type Description
component string Name of the component where the error occurred
statusCode uint32 Status code (conforms to HTTP protocol)
message string error message

Initialization

Create a room by using the GS2-Realtime linkage function of GS2-Matchmaking or by calling GS2-Realtime 's GS2 SDK API Gs2RealtimeRestClient::WantRoom.
After the room is created, a push notification will be sent to the user ID specified in the WantRoom argument.
Triggered by the push notification, GS2RealtimeClient::GetRoom is called to obtain the game server's IP address, standby port, and encryption key.

Even if the participants cannot be determined at the time of room creation, GS2RealtimeClient::GetRoom can be called to retrieve the necessary information as long as there is a way to know the room name.
If you use GS2-Matchmaking's GS2-Realtime function, the gathering name will be used as the room name.

Session Creation

using (
    var session = new RelayRealtimeSession(
        accessToken, // access token
        ipAddress, // IP address of game server
        port, // port of game server
        encryptionKey, // encryption key
        ByteString.CopyFromUtf8("my profile") // Initial profile value
    )
)
{
    // Scope at which the session is valid
}

After the game server has been started, a connection to the game server is made. The RelayRealtimeSession class represents the communication with the game server.

The disconnection process is automatically performed when the scope is exited.

Event Handler Settings

Event Handler Settings

session.OnJoinPlayer += player => {
    // callback processing
};

If necessary, assign callback processing to the event handlers shown earlier.

Connection to the game server

Connection to the game server

yield return session.Connect(
    r =>
    {
        if (r.Error != null)
        {
            // if the connection process fails
        }
    }
)

Connect initiates a connection to the game server.
If an error occurs, the error is passed to the callback.

Data Transmission

Data Transmission

yield return session.Send(
    r => {
        if (r.Error != null)
        {
            throw r.Error;
        }
    },
    ByteString.CopyFrom(0x00, 0x01, 0x02)
)

yield return session.Send(
    r => {
        if (r.Error != null)
        {
            throw r.Error;
        }
    },
    ByteString.CopyFrom(0x00, 0x01, 0x02),
    new uint[] {targetConnectionId1, targetConnectionId2} // Can also specify destination
)

Send sends data to other players.
By specifying an array of destination connection IDs as the third argument, data can be sent only to the specified player.

For example, in a game such as battle royale, where the number of participants is very large and the game is represented by a vast field, the coordinate information of players who are not nearby is not very important.
Therefore, communication can be made more efficient by sending the latest coordinate data only to players who are nearby, based on the approximate coordinates recorded in their profiles at regular intervals (e.g., every 10 seconds).

Update Profile

Update Profile

yield return session.UpdateProfile(
    r =>
    {
        if (r.Error != null)
        {
            throw r.Error;
        }
    },
    ByteString.CopyFromUtf8("my profile2")
)

UpdateProfile updates the profile.
When a profile is updated, OnUpdateProfile is called for all players in the room.
There is no clear limit on the size of the profile, as the appropriate data size depends on the number of participants.

GS2-Schedule

Service Overview

Manage the schedule of in-game events.

This service is not used alone, but in conjunction with GS2-Showcase and GS2-Quest to enable products and quests to be displayed in the store only during the event period.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Create an event master
  2. Use from each service

Create an event master data

Example of triggering from a server (python)


from gs2_schedule_client.request import TriggerByUserIdRequest
from gs2_schedule_client.result import TriggerByUserIdResult

result = client.trigger_by_user_id(
    TriggerByUserIdRequest()\
        .with_namespace_name('schedule-0002')\
        .with_trigger_name('trigger1')\
        .with_user_id('user-0001')\
        .with_trigger_strategy('renew')\
        .with_ttl(ttl)
)

It is created from the Management Console.
When creating the event, you can choose between "Fixed Time" and "Duration by Player" as the type of event duration.

In the case of a fixed time, all players will visit equally when the specified date and time arrives.

For player-specific periods, it is necessary to pull the start trigger. There are two ways to pull the trigger: execute the API from your own server or use GS2-Script.

Use from each service

For example, look at the Quest Group Model Master for GS2-Quest from the Management Console.
You can specify the event you have created by setting the challenge availability period.
This way you can create a quest that can only be attempted during the event period.

Other products can be created by combining with GS2-Showcase, such as limited-time-only products.

GS2-Script

Service Overview

Services for game-specific specifications.

Scripts can be executed by triggering various events within GS2.
For example, an account initialization script can be executed by triggering the event when an account is registered.
A player level-up event can trigger a script to restore stamina, for example.
Scripts can be used to extend functionality when game specifications cannot be realized with standard GS2 functionality.

Pricing

General usage

0.02 yen per API request

Service-specific

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

What to do on the development side

For example, the GS2-Account namespace information allows you to configure scripts to be run during account creation and authentication.

What to do on the game player side

Via GS2-JobQueue

When setting up GS2 scripts in the namespace of each service, the namespace of GS2-JobQueue can be optionally specified.
If specified, the script will not be executed immediately, but will be registered as a job in GS2-JobQueue before being executed.
The advantages of using GS2-JobQueue include the ability to retry up to a certain number of times if a job fails, the fact that jobs that fail more than a certain number of times are recorded as dead letter jobs, and the fact that the API response speed is not slow.
Please check GS2-JobQueue for details.

How to check the result of script execution

Not only GS2-Script, but also GS2-Log must be used to check the execution results of scripts and API calls.

Scripts are executed upon the game player's action (API call), but the return value of the API call does not include the result of the script execution.
If the game player needs to check the result of the script execution, he/she can do so via GS2-JobQueue.

Script Sample

Increase Currency

client = gs2('money')
api_result = client.deposit_by_user_id({
    namespaceName='money',
    userId=args['account']['userId'],
    slot=0,
    price=0,
    count=10000,
})

if(api_result['isError']) then
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result['result']

The following is a sample script that grants an initial in-game currency of 10000 upon completion of account creation.
Arguments (args) are used to grant currency to the created account (userId). The available arguments vary depending on the occasion. Sample arguments can be found on the console's Script Update page.
Sample codes for other scripts can be found in the GS2-Script tab of each GS2 SDK service.

GS2-Showcase

Service Overview

Provide in-game store functionality.

Set a price and a reward for the products to be sold. Multiple resources can be set for both compensation and rewards.

A system called "Product Groups" is used to implement mechanisms such as step gachas and first-time-only discounts.
Product groups are a mechanism to group together multiple products by prioritizing each product, so that the products that meet the requirements for purchase and have the highest priority are displayed.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are two steps to use.

  1. Create a master data
  2. Buy Products

Create a master data

There are three types of master datas.

Merchandise Master data
Product Group Master data
Display shelf master data

Merchandise Master data

You determine the price and reward for your goods.
In addition to exchanging money for in-game currency, you can use in-game currency for various definitions, such as running gachas or increasing stamina.

Product Group Master data

Group product masters. Uses include, for example, registering discount-priced products in order of discount price => regular-priced products when first-time discounts are realized, or registering step-up gachas in order.

Product masters can be sold without grouping them in a product group master.

Display shelf master data

Register the created product master and product group master.
The product master and product group master must be registered in the display shelf master in order to sell the products in the store.

Buy Products

Example implementation for purchasing an exchange (Unity/UniTask enabled)

var domain = gs2.Showcase.Namespace(
    namespaceName: "namespace1" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Showcase(
    showcaseName: "showcase-0001" // product name
);
var result = await domain.BuyAsync(
    displayItemId: "display-item-0001", // display item ID
    config: null // configuration value to apply to stamp sheet variables (optional)
);

var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(item.Name); // product name
Debug.Log(item.Metadata); // Product metadata
Debug.Log(item.ConsumeActions); // Consume action list
Debug.Log(item.AcquireActions); // Acquire action list
Debug.Log(stampSheet); // Stamp sheet used to execute the purchase process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

Example of implementation to purchase exchange (Unity)

AsyncResult<EzBuyResult> asyncResult = null;
var current = gs2.Showcase.Buy(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    showcaseName: "showcase-0001", // product name
    displayItemId: "display-item-0001", // display item ID
    config: null // configuration value to apply to stamp sheet variables (optional)
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var stampSheet = result.StampSheet;
var stampSheetEncryptionKeyId = result.StampSheetEncryptionKeyId;

Debug.Log(item.Name); // product name
Debug.Log(item.Metadata); // Product metadata
Debug.Log(item.ConsumeActions); // Consume action list
Debug.Log(item.AcquireActions); // Acquire action list
Debug.Log(stampSheet); // Stamp sheet used to execute the purchase process
Debug.Log(stampSheetEncryptionKeyId); // encryption key GRN used for stamp sheet signature calculation

It is important to note that simply executing 'buy' itself does not result in the purchase of goods.
It is done by processing the stamp sheet that is the return value of 'buy'.
For more information on stamp sheets, please refer to the Stamp Sheet page.
If you want to set multiple rewards for one product, you need to work with GS2-JobQueue.

GS2-Stamina

Service Overview

Realize a stamina value that recovers with the passage of real time.

Stamina can be set to a recovery interval and recovery amount.
Stamina can be set to a maximum of two levels.
The first is the maximum value for natural recovery over time, and the second is the maximum value for UI reasons.

In GS2, when all stamina is restored upon leveling up, it can be restored beyond the maximum natural recovery value to ensure fairness.
On the other hand, if this were allowed without limitation, the UI might break down.
For this reason, a second maximum level is set so that even if the maximum is exceeded, GS2-Distributor can still deliver stamina recovery resources to the gift box.

This mechanism can also be applied to implement a foraging function in a city-building game.
Set up buildings in the stamina model and represent stamina values as the production of buildings.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Limit the number of operations on the same stamina to 3 operations per second.
This limit does not apply to operations on different users or different stamina models for the same user.

Basic usage

There are two steps to use.

  1. Create a master data
  2. Consume Stamina

Create a master data

There are four types of master datas.

Stamina Model Master data

Defines the maximum value of stamina, recovery interval, and amount of recovery.

However, many stamina-based games will have a maximum value that increases with the player's rank.
To achieve this, use the GS2-Experience link at the bottom of the Stamina Model Master Settings page.
How to use it is explained in the next section.

Maximum Stamina Table Master data

This setting changes the maximum value of stamina depending on the player's rank.
Player ranks are realized in GS2-Experience.
Create an experience type master (which defines which rank for each experience) in advance.
Please check the GS2-Experience page here.

Once you have created the experience type master, you can register it in the maximum stamina table master, and
Now define the maximum value of stamina for each rank.
Remember to register the maximum value of stamina table master in the stamina model master after it is created.

Restore stamina when ranks are upgraded

In many stamina-based games, stamina is restored to its maximum value when a player ranks up.
To achieve this, use GS2-Script.
Create a GS2-Script that restores the maximum amount of Stamina, and then use the
Register it in the script to be executed when the rank changes in the GS2-Experience namespace setting.

Please check the GS2-Script page here.

Stamina Recovery Interval Table Master data & Stamina Recovery Amount Table Master data

In addition to the maximum stamina table master, this master also changes the recovery interval and amount of recovery depending on rank.
However, in many stamina-based games, there are few that even vary the efficiency of stamina recovery.

One possible use would be a system in which resources are obtained over time, such as in the game's fields and mines.
Stamina can be thought of as the amount of resources, and the efficiency of obtaining resources can be varied depending on the level of the facility.

Consume Stamina

There are two ways to consume stamina.

Consumption on stamp sheets

For example, open GS2-Quest => Quest Group Model Master => Quest Model Master in the Management Console.
You can select "Stamina: Consume Stamina" as the participation fee for the quest. In this way, you can implement a system that works with other services to consume Stamina to do something.

Consumption by calling API from client or server

Example of consuming stamina from a client (Unity/UniTask enabled)

var domain = gs2.Stamina.Namespace(
    namespaceName: "namespace2" // namespace name
).Me(
    gameSession: gameSession // GameSession object (access token)
).Stamina(
    staminaName: "stamina-0001" // name of stamina type
);
var result = await domain.ConsumeAsync(
    consumeValue: 50 // amount of stamina to consume
);
var item = await result.ModelAsync();
var staminaModel = result.StaminaModel;

Debug.Log(item.StaminaName); // name of stamina model
Debug.Log(item.Value); // Stamina value at last update
Debug.Log(item.MaxValue); // maximum value of stamina
Debug.Log(item.RecoverIntervalMinutes); // Stamina recovery interval (minutes)
Debug.Log(item.RecoverValue); // Stamina recovery amount
Debug.Log(item.NextRecoverAt); // Time for next time stamina is recovered
Debug.Log(staminaModel.Name); // name of stamina type
Debug.Log(staminaModel.Metadata); // Metadata of stamina type
Debug.Log(staminaModel.RecoverIntervalMinutes); // Speed at which stamina is recovered (minutes)
Debug.Log(staminaModel.RecoverValue); // Amount of time to recover after
Debug.Log(staminaModel.InitialCapacity); // Initial maximum value of stamina
Debug.Log(staminaModel.IsOverflow); // whether recovery exceeds the maximum
Debug.Log(staminaModel.MaxCapacity); // Maximum value in overflow situation
Debug.Log(staminaModel.MaxStaminaTable.Name); // maximum stamina value table name
Debug.Log(staminaModel.MaxStaminaTable.Metadata); // Metadata for the maximum stamina value table
Debug.Log(staminaModel.MaxStaminaTable.ExperienceModelId); // GRN of the experience type master
Debug.Log(staminaModel.MaxStaminaTable.Values); // Maximum stamina table per rank
Debug.Log(staminaModel.RecoverIntervalTable.Name); // name of stamina recovery interval table
Debug.Log(staminaModel.RecoverIntervalTable.Metadata); // Stamina recovery interval table metadata
Debug.Log(staminaModel.RecoverIntervalTable.ExperienceModelId); // GRN of experience type master
Debug.Log(staminaModel.RecoverIntervalTable.Values); // Stamina recovery interval table per rank
Debug.Log(staminaModel.RecoverValueTable.Name); // Stamina recovery amount table name
Debug.Log(staminaModel.RecoverValueTable.Metadata); // Stamina recovery amount table metadata
Debug.Log(staminaModel.RecoverValueTable.ExperienceModelId); // GRN of the experience type master
Debug.Log(staminaModel.RecoverValueTable.Values); // Stamina recovery amount table per rank

Example of consuming stamina from client (Unity)

AsyncResult<EzConsumeResult> asyncResult = null;
var current = gs2.Stamina.Consume(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace2", // namespace name
    staminaName: "stamina-0001", // name of stamina type
    consumeValue: 50 // amount of stamina to consume
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var item = result.Item;
var staminaModel = result.StaminaModel;

Debug.Log(item.StaminaName); // name of stamina model
Debug.Log(item.Value); // Stamina value at last update
Debug.Log(item.MaxValue); // maximum value of stamina
Debug.Log(item.RecoverIntervalMinutes); // Stamina recovery interval (minutes)
Debug.Log(item.RecoverValue); // Stamina recovery amount
Debug.Log(item.NextRecoverAt); // Time for next time stamina is recovered
Debug.Log(staminaModel.Name); // name of stamina type
Debug.Log(staminaModel.Metadata); // Metadata of stamina type
Debug.Log(staminaModel.RecoverIntervalMinutes); // Speed at which stamina is recovered (minutes)
Debug.Log(staminaModel.RecoverValue); // Amount of time to recover after
Debug.Log(staminaModel.InitialCapacity); // Initial maximum value of stamina
Debug.Log(staminaModel.IsOverflow); // whether recovery exceeds the maximum
Debug.Log(staminaModel.MaxCapacity); // Maximum value in overflow situation
Debug.Log(staminaModel.MaxStaminaTable.Name); // maximum stamina value table name
Debug.Log(staminaModel.MaxStaminaTable.Metadata); // Metadata for the maximum stamina value table
Debug.Log(staminaModel.MaxStaminaTable.ExperienceModelId); // GRN of the experience type master
Debug.Log(staminaModel.MaxStaminaTable.Values); // Maximum stamina table per rank
Debug.Log(staminaModel.RecoverIntervalTable.Name); // name of stamina recovery interval table
Debug.Log(staminaModel.RecoverIntervalTable.Metadata); // Stamina recovery interval table metadata
Debug.Log(staminaModel.RecoverIntervalTable.ExperienceModelId); // GRN of experience type master
Debug.Log(staminaModel.RecoverIntervalTable.Values); // Stamina recovery interval table per rank
Debug.Log(staminaModel.RecoverValueTable.Name); // Stamina recovery amount table name
Debug.Log(staminaModel.RecoverValueTable.Metadata); // Stamina recovery amount table metadata
Debug.Log(staminaModel.RecoverValueTable.ExperienceModelId); // GRN of the experience type master
Debug.Log(staminaModel.RecoverValueTable.Values); // Stamina recovery amount table per rank

Example of consuming stamina from the server (Unity)


from gs2_stamina_client.request import ConsumeStaminaByUserIdRequest
from gs2_stamina_client.result import ConsumeStaminaByUserIdResult

result = client.consume_stamina_by_user_id(
    ConsumeStaminaByUserIdRequest()\
        .with_namespace_name('namespace-0002')\
        .with_stamina_name('stamina-0002')\
        .with_user_id('user-0001')\
        .with_consume_value(5)
)

Unlike the previous section, use this if you wish to consume stamina in the game's own system.

GS2-Version

Service Overview

Realize a version check of the game.
If the game passes the version check, you will get a new project token.
In other words, the credential to be included in the game should be granted only enough privileges to perform the version check, and
By ensuring that passing the version check will allow you to obtain a project token with sufficient privileges to run the game, you can
It creates a situation where the game cannot be played unless it passes the version check.

Up to 10 version models can be declared in the namespace, and a version check is considered passed only when all versions are greater than or equal to the required version.

Pricing

General usage

0.02 yen per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

There are no restrictions or limitations on the use of this service.

Basic usage

There are three steps to use.

  1. Create a master data
  2. Creating a security policy that can perform version authentication
  3. Authenticate version

Create a master data

Create from the Management Console.
The version set in the version master will be the version to inform the client that it is not the latest or similar version.
Therefore, the latest version will not be registered in the master.

The fact that the version of the client did not match the version registered in the master proves that the version is acceptable for playing the game.

Up to 10 version masters can be registered per namespace, and the game can be played if a maximum of 10 version checkpoints can be passed.

Create a security policy that allows only version authentication to be performed

The basic procedure for using the system is as follows

1.Only grant the game credentials with sufficient privileges to perform version checking.
2.After launching the game, first perform a version check using the credentials in 1.
- If the version check passes, have the client obtain enough project tokens to run the game.
- If the version check does not pass, direct the user to the app store, etc. to upgrade the version.

You must create credentials with sufficient privileges to perform version checking here.
Please see the GS2-Identifier page for more information on this.

Authenticate version

To authenticate the version, first prepare the client's version information.

Example of preparing client version information (Unity)

List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.VersionName = "test";
EzVersion version = new EzVersion();
version.Major = 1; //input actual client version Major version
version.Minor = 2; //Enter actual client version Minor version
version.Micro = 3; //input actual client version Micro version
targetVersion.Version = version;
targetVersions.Add(targetVersion);

Next, the API for version authentication is executed with the version information as an argument.

Example of version checking (Unity)

AsyncResult<EzCheckVersionResult> asyncResult = null;
var current = gs2.Version.CheckVersion(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace1", // namespace name
    targetVersions: new Gs2.Gs2Version.Model.TargetVersion[] {
        {'versionName': 'app', 'version': {'major': 1, 'minor': 2, 'micro': 3}},
        {'versionName': 'asset', 'version': {'major': 1, 'minor': 2, 'micro': 3}}
    } // Version list to be verified
);

yield return current;
if (asyncResult.Error != null)
{
    OnError(asyncResult.Error);
    yield break;
}

var result = asyncResult.Result;
var projectToken = result.ProjectToken;
var warnings = result.Warnings;
var errors = result.Errors;

Debug.Log(projectToken); // project token
Debug.Log(warnings); // list of version validation results
Debug.Log(errors); // List of version verification results

The return values 'Warnings' and 'Errors' contain information on versions that failed to pass.
Since 'Warnings' and 'Errors' are lists, they are not
If the size of each is 0, there is no problem with the version = start the game, if the size of each is 0, there is no problem with the version = start the game.
If either size is greater than 1, there is a version problem = prompt to upgrade.
The process can be written as follows.

Stamp Sheet

What is a stamp sheet?

Stamp sheet concept

GS2 has a system called StampSheet that links all services together.
It enables the implementation of processes that are conditional on the execution of resource operations and other operations that are performed by other services.

The stamp sheet is a system similar to the approval process in a company.
When each service gives its approval, it puts a stamp ( signature) on it, and when everything is in order, the process can be executed.

The process of consuming resources, etc., necessary for approval is called a stamp task.
A stamp is obtained if each service is able to execute the requested stamp task.
When all stamps have been placed on a stamp sheet, the stamp sheet is processed and
The processing of each stamp task can be executed.

For example, if you are processing rewards for completing a quest
Stamp tasks can be set up to reducestamina values or the number of orders that can be taken, and can be used to reduce the number of orders that can be taken.
As a reward for the consumption, the user gets experience, and the quest clear flag is rewritten.
The process is then executed together at the end of the process.

Example of master data for a quest using stamp sheets (JSON format)

{
  "version": "2019-05-14",
  "groups": [
    {
      "name": "main",
      "metadata": "Main Scenario",
      "quests": [
        {
          "name": "chapter-0001",
          "metadata": "Chapter 1. The beginning of the adventure",
          "contents": [
            {
              "metadata": "NORMAL",
              "completeAcquireActions": [
                {
                  "action": "Gs2Money:DepositByUserId",
                  "request": "{\"namespaceName\": \"money-0001\", \"userId\": \"#{userId}\", \"slot\": \"#{slot}\", \"price\": \"0\", \"count\": \"10\"}"
                },
                {
                  "action": "Gs2Money:DepositByUserId",
                  "request": "{\"namespaceName\": \"money-0001\", \"userId\": \"#{userId}\", \"slot\": \"#{slot}\", \"price\": \"0\", \"count\": \"10\"}"
                }
              ],
              "weight": 95
            },
            {
              "metadata": "RARE",
              "completeAcquireActions": [
                {
                  "action": "Gs2Money:DepositByUserId",
                  "request": "{\"namespaceName\": \"money-0001\", \"userId\": \"#{userId}\", \"slot\": \"#{slot}\", \"price\": \"0\", \"count\": \"20\"}"
                },
                {
                  "action": "Gs2Money:DepositByUserId",
                  "request": "{\"namespaceName\": \"money-0001\", \"userId\": \"#{userId}\", \"slot\": \"#{slot}\", \"price\": \"0\", \"count\": \"10\"}"
                }
              ],
              "weight": 5
            }
          ],
          "consumeActions": [
            {
              "action": "Gs2Stamina:ConsumeStaminaByUserId",
              "request": "{\"namespaceName\": \"stamina-0001\", \"staminaName\": \"main\", \"userId\": \"#{userId}\", \"consumeValue\": \"10\"}"
            }
          ],
          "failedAcquireActions": [
            {
              "action": "Gs2Stamina:RecoverStaminaByUserId",
              "request": "{\"namespaceName\": \"stamina-0001\", \"staminaName\": \"main\", \"userId\": \"#{userId}\", \"recoverValue\": \"10\"}"
            }
          ],
          "premiseQuestNames": [],
          "questModelId": "grn:gs2:ap-northeast-1:sampleproject:quest:quest-0001:group:main:quest:chapter-0001"
        }

      ],
      "questGroupModelId": "grn:gs2:ap-northeast-1:sampleproject:quest:quest-0001:group:main"
    }
  ]
}

Stamp Sheet Variables

A stamp sheet or stamp task issues a request to the respective GS2 services.

The Stamp Task is a task to fulfill the conditions necessary to execute the API of the target service of the Stamp Sheet, and
Actions (consumeActions) can be set to reduce user resources.

The Stamp Sheet can have actions that increase the user's resources upon completion (completeAcquireActions), actions that increase the user's resources upon
Actions can be set to return user resources on failure (failedAcquireActions).

Parameter settings for stamp sheet issuance

Example of using Config(EzConfig) to replace strings in a stamp sheet issue request

Example of a stamp sheet (JSON format) that adds the balance to the wallet

"salesItem": {
  "name": "currency-120-jpy",
  "metadata": "price: 120 currencyCount: 50",
  "consumeActions": [
    {
      "action": "Gs2Money:RecordReceipt",
      "request": "{\"namespaceName\": \"money-0001\", \"contentsId\": \"io.gs2.sample.currency120\", \"userId\": \"#{userId}\", \"receipt\": \"#{receipt}\"}"
    }
  ],
  "acquireActions": [
    {
      "action": "Gs2Money:DepositByUserId",
      "request": "{\"namespaceName\": \"money-0001\", \"userId\": \"#{userId}\", \"slot\": \"#{slot}\", \"price\": 120, \"count\": 50}"
    }
  ]
}

Example of stamp sheet to add balance to wallet (GS2-Deploy template YAML format)

- type: salesItem
  salesItem:
    name: currency-120-jpy
    metadata: "price: 120 currencyCount: 50"
    consumeActions:
      - action: Gs2Money:RecordReceipt
        request:
          namespaceName: ${MoneyNamespaceName}
          contentsId: io.gs2.sample.currency120
          userId: "#{userId}"
          receipt: "#{receipt}"
    acquireActions:
      - action: Gs2Money:DepositByUserId
        request:
          namespaceName: ${MoneyNamespaceName}
          userId: "#{userId}"
          slot: "#{slot}"
          price: 120
          count: 50

Example of replacing a placeholder string using Config(EzConfig)

AsyncResult<EzBuyResult> result = null;
yield return client.Showcase.Buy(
    r => { result = r; },
    session,
    showcaseNamespaceName,
    showcaseName,
    selectedProduct.Id,
    new List<EzConfig>
    {
        new EzConfig
        {
            Key = "slot", // #{slot} is replaced by Slot (slot number)
            Value = Slot.ToString(),
        },
        new EzConfig
        {
            Key = "receipt", // #{receipt} is replaced with receipt (receipt string)
            Value = receipt,
        },
    }
);

Each request to a service requires information about which user's resources are to be manipulated, but
User IDs cannot be statically specified in advance in the master data of in-game stores and quests.
Therefore, a variable can be embedded in the Stamp Sheet request.

If you set the placeholder string #{userId} in the request for the master data action
When issuing a Stamp Sheet, that portion is replaced with the user ID of the user who issued the Stamp Sheet.

In addition, a parameter Config(EzConfig) can be passed to the request to issue Stamp Sheet.
Config(EzConfig) is a key-value format parameter that can be used to replace the #{Key value specified in Config} placeholder string.

Stamp task execution results

If we set the placeholder ${Gs2Money:WithdrawByUserId.price} as an example in the content of the action request (JSON)
That portion will be replaced by the result of the stamp task execution and can be used as a variable.
In the case shown in the example, the result of the execution of Gs2Money:WithdrawByUserId among the executed tasks is referenced and the returned price is used as the value.
Child elements can be referenced by connecting them with a dot, such as ${Gs2Money:WithdrawByUserId.item.paid}.

The value adopted when the same action is registered as multiple stamp tasks is undefined.

List of Stamp Sheets

Gs2Dictionary:AddEntriesByUserId

Add an entry by the stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "entryModelNames": "[string[]]List of Entry Names"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
entryModelNames string[] [] List of Entry Names

Gs2Enhance:DirectEnhanceByUserId

Perform enhancements with stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "rateName": "[string]Enhanced Rate Name",
  "userId": "#{userId}",
  "targetItemSetId": "[string]Quantity of items held per expiration date GRN",
  "materials": "[Material[]]List of Material",
  "config": "[Config[]]Set values to be applied to stamp sheet variables"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
rateName string ~ 128 chars Enhanced Rate Name
userId string ~ 128 chars User Id
targetItemSetId string ~ 1024 chars Quantity of items held per expiration date GRN
materials Material[] List of Material
config Config[] [] Set values to be applied to stamp sheet variables

Gs2Enhance:CreateProgressByUserId

Start enhancement with stamp sheets.

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "rateName": "[string]Rate Model Name",
  "targetItemSetId": "[string]Quantity of items held per expiration date GRN",
  "materials": "[Material[]]List of materials",
  "force": "[bool]If there is an enhancement that has already been started, it can be discarded and started, or"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
rateName string ~ 128 chars Rate Model Name
targetItemSetId string ~ 1024 chars Quantity of items held per expiration date GRN
materials Material[] List of materials
force bool false If there is an enhancement that has already been started, it can be discarded and started, or

Gs2Exchange:ExchangeByUserId

Perform exchange with stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "rateName": "[string]Exchange Rate Name",
  "userId": "#{userId}",
  "count": "[int]Number of lots to be exchanged",
  "config": "[Config[]]Set values to be applied to stamp sheet variables"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
rateName string ~ 128 chars Exchange Rate Name
userId string ~ 128 chars User Id
count int 1 ~ 2147483646 Number of lots to be exchanged
config Config[] [] Set values to be applied to stamp sheet variables

Gs2Exchange:CreateAwaitByUserId

Create a standby exchange with a stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "rateName": "[string]Exchange rate name",
  "count": "[int]Number of exchanges"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
rateName string ~ 128 chars Exchange rate name
count int 1 1 ~ 10000 Number of exchanges

Gs2Experience:AddExperienceByUserId

Use stamp sheets to add experience

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "experienceName": "[string]Experience Model Name",
  "propertyId": "[string]Property ID",
  "experienceValue": "[long]Gained Experience"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
experienceName string ~ 128 chars Experience Model Name
propertyId string ~ 1024 chars Property ID
experienceValue long 0 ~ 9223372036854775806 Gained Experience

Gs2Experience:AddRankCapByUserId

Use stamp sheet to add rank cap

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "experienceName": "[string]Experience Model Name",
  "propertyId": "[string]Property ID",
  "rankCapValue": "[long]Current Rank Cap"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
experienceName string ~ 128 chars Experience Model Name
propertyId string ~ 1024 chars Property ID
rankCapValue long ~ 9223372036854775806 Current Rank Cap

Gs2Experience:SetRankCapByUserId

Update rank caps with stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "experienceName": "[string]Experience Model Name",
  "propertyId": "[string]Property ID",
  "rankCapValue": "[long]Current Rank Cap"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
experienceName string ~ 128 chars Experience Model Name
propertyId string ~ 1024 chars Property ID
rankCapValue long ~ 9223372036854775806 Current Rank Cap

Gs2Formation:AddMoldCapacityByUserId

Use stamp sheets to add capacity size

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "moldName": "[string]Form Name",
  "capacity": "[int]Current Capacity"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
moldName string ~ 128 chars Form Name
capacity int ~ 2147483646 Current Capacity

Gs2Formation:SetMoldCapacityByUserId

Use stamp sheet to set capacity size

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "moldName": "[string]Form Name",
  "capacity": "[int]Current Capacity"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
moldName string ~ 128 chars Form Name
capacity int ~ 2147483646 Current Capacity

Gs2Formation:AcquireActionsToFormProperties

Add resources to properties to be organized using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "moldName": "[string]Mold Name",
  "index": "[int]Index of storage area",
  "acquireAction": "[AcquireAction]Get action to be applied to form properties",
  "queueNamespaceId": "[string]Namespace in GS2-JobQueue used to run the stamp sheet",
  "keyId": "[string]GS2-Key namespace used to issue stamp sheets",
  "config": "[AcquireActionConfig[]]List of Acquisition config"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
moldName string ~ 128 chars Mold Name
index int ~ 2147483646 Index of storage area
acquireAction AcquireAction Get action to be applied to form properties
queueNamespaceId string ~ 1024 chars Namespace in GS2-JobQueue used to run the stamp sheet
keyId string ~ 1024 chars GS2-Key namespace used to issue stamp sheets
config AcquireActionConfig[] [] List of Acquisition config

Gs2Inbox:SendMessageByUserId

Send a message using the stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "metadata": "[string]Metadata corresponding to the content of the message",
  "readAcquireActions": "[AcquireAction[]]Obtain actions to be performed upon opening",
  "expiresAt": "[long]Message Expiration Date",
  "expiresTimeSpan": "[TimeSpan_]Difference up to the expiration date of the message"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
metadata string ~ 4096 chars Metadata corresponding to the content of the message
readAcquireActions AcquireAction[] [] Obtain actions to be performed upon opening
expiresAt long Message Expiration Date
expiresTimeSpan TimeSpan_ Difference up to the expiration date of the message

Gs2Inventory:AddCapacityByUserId

Use stamp sheets to add capacity size

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "addCapacityValue": "[int]Capacity size to be added"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
addCapacityValue int 1 ~ 2147483646 Capacity size to be added

Gs2Inventory:SetCapacityByUserId

Use stamp sheet to set capacity size

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "newCapacityValue": "[int]New maximum capacity for inventory"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
newCapacityValue int 1 ~ 2147483646 New maximum capacity for inventory

Gs2Inventory:AcquireItemSetByUserId

Add items to inventory using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Name",
  "itemName": "[string]Item Model Name",
  "userId": "#{userId}",
  "acquireCount": "[long]Quantity to be obtained",
  "expiresAt": "[long]Effective date",
  "createNewItemSet": "[bool]Even if there is room in an existing ItemSet, you can create a new ItemSet",
  "itemSetName": "[string]Name identifying the item set"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Name
itemName string ~ 128 chars Item Model Name
userId string ~ 128 chars User Id
acquireCount long 1 ~ 9223372036854775806 Quantity to be obtained
expiresAt long 0 Effective date
createNewItemSet bool false Even if there is room in an existing ItemSet, you can create a new ItemSet
itemSetName string ~ 36 chars Name identifying the item set

Gs2Inventory:AddReferenceOfByUserId

Add a reference to an item using a stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "itemName": "[string]Item Model Name",
  "itemSetName": "[string]Name identifying the item set",
  "referenceOf": "[string]References for this possession"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
itemName string ~ 128 chars Item Model Name
itemSetName string UUID ~ 36 chars Name identifying the item set
referenceOf string ~ 1024 chars References for this possession

Gs2Inventory:DeleteReferenceOfByUserId

Delete item references using stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "itemName": "[string]Item Model Name",
  "itemSetName": "[string]Name identifying the item set",
  "referenceOf": "[string]References for this possession"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
itemName string ~ 128 chars Item Model Name
itemSetName string UUID ~ 36 chars Name identifying the item set
referenceOf string ~ 1024 chars References for this possession

Gs2JobQueue:PushByUserId

Register jobs using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "jobs": "[JobEntry[]]List of Jobs"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
jobs JobEntry[] List of Jobs

Gs2Limit:DeleteCounterByUserId

Delete counter using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "limitName": "[string]Name of limit model",
  "userId": "#{userId}",
  "counterName": "[string]Counter Name"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
limitName string ~ 128 chars Name of limit model
userId string ~ 128 chars User Id
counterName string ~ 128 chars Counter Name

Gs2Lottery:DrawByUserId

Perform the lottery process using a stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "lotteryName": "[string]Name of lottery model type",
  "userId": "#{userId}",
  "count": "[int]Number of draws",
  "config": "[Config[]]Stamp sheet placeholder applied settings values"
}
Type Require Default Limitation Description
namespaceName string ~ 128 chars Namespace name
lotteryName string ~ 128 chars Name of lottery model type
userId string ~ 128 chars User Id
count int 1 ~ 1000 Number of draws
config Config[] [] Stamp sheet placeholder applied settings values

Gs2Mission:IncreaseCounterByUserId

Use stamp sheets to add counters

{
  "namespaceName": "[string]Namespace name",
  "counterName": "[string]Counter Name",
  "userId": "#{userId}",
  "value": "[long]Value to be added"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
counterName string ~ 128 chars Counter Name
userId string ~ 128 chars User Id
value long 1 ~ 9223372036854775806 Value to be added

Gs2Money:DepositByUserId

Add balance to wallet using stamp sheet

{
  "namespaceName": "[string]Namespace Name",
  "userId": "#{userId}",
  "slot": "[int]Slot Number",
  "price": "[float]Purchase Price",
  "count": "[int]Quantity of billable currency to be granted"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace Name
userId string ~ 128 chars User Id
slot int ~ 100000000 Slot Number
price float ~ 100000.0 Purchase Price
count int 1 ~ 2147483646 Quantity of billable currency to be granted

Gs2Quest:CreateProgressByUserId

Start quest with a stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "questModelId": "[string]Quest model GRN in progress",
  "force": "[bool]If have a quest already started, you can discard it and start it",
  "config": "[Config[]]Set values to be applied to stamp sheet variables"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
questModelId string ~ 1024 chars Quest model GRN in progress
force bool false If have a quest already started, you can discard it and start it
config Config[] [] Set values to be applied to stamp sheet variables

Gs2Stamina:RecoverStaminaByUserId

Use stamp sheets to restore stamina

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "recoverValue": "[int]Amount of stamina recovery"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
recoverValue int 1 ~ 2147483646 Amount of stamina recovery

Gs2Stamina:RaiseMaxValueByUserId

Use stamp sheets to add maximum stamina

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "raiseValue": "[int]Maximum amount of stamina to be increased"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
raiseValue int ~ 2147483646 Maximum amount of stamina to be increased

Gs2Stamina:SetMaxValueByUserId

Update maximum stamina with stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "maxValue": "[int]Maximum Stamina"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
maxValue int 1 ~ 2147483646 Maximum Stamina

Gs2Stamina:SetRecoverIntervalByUserId

Update maximum stamina with stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "recoverIntervalMinutes": "[int]Stamina recovery interval (minutes)"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
recoverIntervalMinutes int 1 ~ 2147483646 Stamina recovery interval (minutes)

Gs2Stamina:SetRecoverValueByUserId

Stamina recovery value updated using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "recoverValue": "[int]Amount of stamina recovery"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
recoverValue int 1 ~ 2147483646 Amount of stamina recovery

List of Stamp Tasks

Gs2Enhance:DeleteProgressByUserId

Remove Running Enhancement in Stamp Tasks

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "rateName": "[string]Rate Model Name",
  "progressName": "[string]Conduct ID"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
rateName string ~ 128 chars Rate Model Name
progressName string UUID ~ 36 chars Conduct ID

Gs2Exchange:DeleteAwaitByUserId

Delete Waiting for Exchange in Stamp Task

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "rateName": "[string]Exchange rate name",
  "awaitName": "[string]Exchange standby name"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
rateName string ~ 128 chars Exchange rate name
awaitName string UUID ~ 36 chars Exchange standby name

Gs2Inbox:OpenMessageByUserId

Marking messages as opened using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "messageName": "[string]Message Name"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
messageName string UUID ~ 36 chars Message Name

Gs2Inventory:ConsumeItemSetByUserId

Consume inventory items using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "itemName": "[string]Item Model Name",
  "consumeCount": "[long]Amount to consume",
  "itemSetName": "[string]Name identifying the item set"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
itemName string ~ 128 chars Item Model Name
consumeCount long 1 ~ 9223372036854775806 Amount to consume
itemSetName string ~ 36 chars Name identifying the item set

Gs2Inventory:VerifyReferenceOfByUserId

Verify inventory items using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "inventoryName": "[string]Inventory Model Name",
  "userId": "#{userId}",
  "itemName": "[string]Item Model Name",
  "itemSetName": "[string]Name identifying the item set",
  "referenceOf": "[string]References for this possession",
  "verifyType": "[string]Type of verification"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
inventoryName string ~ 128 chars Inventory Model Name
userId string ~ 128 chars User Id
itemName string ~ 128 chars Item Model Name
itemSetName string UUID ~ 36 chars Name identifying the item set
referenceOf string ~ 1024 chars References for this possession
verifyType string ~ 128 chars Type of verification

Gs2Limit:CountUpByUserId

Count up using stamp sheet

{
  "namespaceName": "[string]Namespace name",
  "limitName": "[string]Name of limit model",
  "counterName": "[string]Counter Name",
  "userId": "#{userId}",
  "countUpValue": "[int]Amount to count up",
  "maxValue": "[int]Maximum value allowed to count up"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
limitName string ~ 128 chars Name of limit model
counterName string ~ 128 chars Counter Name
userId string ~ 128 chars User Id
countUpValue int 1 1 ~ 2147483646 Amount to count up
maxValue int 1 ~ 2147483646 Maximum value allowed to count up

Gs2Mission:ReceiveByUserId

Create achievement status

{
  "namespaceName": "[string]Namespace name",
  "missionGroupName": "[string]Mission Group Name",
  "missionTaskName": "[string]Task Name",
  "userId": "#{userId}"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
missionGroupName string ~ 128 chars Mission Group Name
missionTaskName string ~ 128 chars Task Name
userId string ~ 128 chars User Id

Gs2Money:WithdrawByUserId

Consume balance from wallet using stamp sheet

{
  "namespaceName": "[string]Namespace Name",
  "userId": "#{userId}",
  "slot": "[int]Slot Number",
  "count": "[int]Quantity of billable currency to be consumed",
  "paidOnly": "[bool]Only for paid currency"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace Name
userId string ~ 128 chars User Id
slot int ~ 100000000 Slot Number
count int 1 ~ 2147483646 Quantity of billable currency to be consumed
paidOnly bool false Only for paid currency

Gs2Money:RecordReceipt

Use stamp sheets to record receipts

{
  "namespaceName": "[string]Namespace Name",
  "userId": "#{userId}",
  "contentsId": "[string]Content IDs sold on the store platform",
  "receipt": "[string]Receipt"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace Name
userId string ~ 128 chars User Id
contentsId string ~ 1024 chars Content IDs sold on the store platform
receipt string ~ 1048576 chars Receipt

Gs2Quest:DeleteProgressByUserId

Delete Quest Progress in Stamp Tasks

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id

Gs2Stamina:ConsumeStaminaByUserId

Use Stamp Tasks to Consume Stamina

{
  "namespaceName": "[string]Namespace name",
  "staminaName": "[string]Stamina Model Name",
  "userId": "#{userId}",
  "consumeValue": "[int]Amount of stamina consumed"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
staminaName string ~ 128 chars Stamina Model Name
userId string ~ 128 chars User Id
consumeValue int 1 ~ 2147483646 Amount of stamina consumed

Glossary

General

GRN Format

grn:gs2:{region}:{owner id}:{service name}:{model name}:{alternate key}:{model name}:{alternate key}...

Region Type

ap-northeast-1 = Japan

Policy Document Format

List the actions that can be called in Actions and the target resources that can be manipulated in Resources.

Actions / Resources can only use trailing wildcards

{
"Version": "2016-04-01",
"Statements": [
{
"Effect": "Allow",
"Actions": [
"Gs2Account:Create*",
],
"Resources": ["*"],
},
] }
terminology meaning
GRN Gs2 Resource Name
Unique resource name assigned to all information handled by GS2
service name GS2 microservice types
region Location of the data center where GS2 is operating.
account ID ID to uniquely identify the GS2 account
project ID An ID to uniquely identify a game, managed by linking multiple IDs to an account ID
owner ID {account ID}${project ID}
Data in GS2 is basically stored in connection with this information.
user ID ID that identifies the game player
access token Token issued as proof that the game player has been authenticated by GS2-Auth
Used by each microservice to identify the user's user ID.

It has an expiration date and must be reacquired within 10 hours of issuance.
project token A temporary authentication token obtained using credentials.
Implemented on an Open ID Connect basis, it is, in Open ID Connect terms, an identity token.

It has an expiration date and must be reacquired within 10 hours of issuance.
Security Policy Authorization to be managed in conjunction with the GS2-Identifier user
Define which API operations can be performed using the client ID
policy document JSON document defining security policy authorization settings
model Type of entity in GS2
entity Materialization of the model
alternative key Field names that contain entity-specific values other than the entity's GRN
GS2-Account's Game: gameName, Account: userId, TakeOver: type, userIdentifier
action An identifier for the API type, defined as Gs2Inbox:CreateInbox, where the first half represents the service and the second half represents the type of action.
property ID ID to uniquely identify a character or item in a game
Resource GRN Generic name for GRNs of game player's possessions
GS2-Inventory possessions, GS2-Experience experience information, GS2-Stamina stamina values, etc.
request ID ID assigned to each API request to GS2
The same request ID is shared for API accesses in GS2-Script derived from that API, etc.

Request IDs make it possible to trace the flow of a series of processes, and
In transaction processing, deadlocks caused by the same processor can be avoided.
context Name of the stack area allocated to the GS2 request ID
Or the status of the stack area in the processor of the same request ID.
stack area Memory space stacked for each process chain in a processing system with the same request ID

GS2-Account

terminology meaning
Account credentials and signature Information issued upon successful authentication by GS2-Account. Tamper detection is possible when used in conjunction with a signature.
transfer settings Settings for restoring user IDs and passwords issued by GS2-Account. Holds user ID and password that can be set to any value needed to perform the handover.

GS2-Identifier

terminology meaning
client ID ID to identify API users
GS2-Identifier, which is associated with a user and managed
client secret Key to identify that the client ID is being used by an authorized user
credential Client ID and Client Secret combination

GS2-Money

terminology meaning
billing currency In-game currency that falls under the category of prepaid means of payment (in-house type) under the Funds Settlement Act

GS2-Matchmaking

terminology meaning
gathering A set of players created by matchmaking
roll Roles of players used for conditions during matchmaking (tank, healer, etc.)

Inter-service dependency

GS2-Account

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Signature issuance of certification results always
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Auth

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Signature verification of GS2-Account authentication results When trying to issue an access token using GS2-Account authentication results

GS2-Chat

Dependent Services Reasons to Depend Dependent Conditions
GS2-Script::Script Script Execution When a script is set for an event
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Distributor

Dependent Services Reasons to Depend Dependent Conditions
GS2-Identifier::User Requires a user with execute permission to execute a reward grant always
GS2-Inbox::Namespace Needed to deliver overflow rewards to GS2-Inbox Dependent on performing a reward grant to GS2-Inventory/GS2-Stamina
All other For stamp sheet execution Depends on microservices set for stamp sheet compensation and rewards

GS2-Exchange

Dependent Services Reasons to Depend Dependent Conditions
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on setting multiple rewards
GS2-Key::Key Signature issue of stamp sheets always
All other To issue stamp sheets Depends on microservices to be set up for stamp sheet compensation and rewards

GS2-Experience

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on giving rewards with stamp sheets.
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Formation

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on giving rewards with stamp sheets.
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Friend

Dependent Services Reasons to Rely Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on giving rewards with stamp sheets.
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-Gateway::Namespace Friend Request Notification Dependent on setting up to receive push notifications using always-on communication sessions

GS2-Gateway

Dependent Services Reasons to Depend Dependent Conditions
Firebase::FCM Send mobile push notifications Depends if the option to forward to mobile push if the target user is offline at the time of the push notification request is enabled

GS2-Identifier

Dependent Services | Reasons to Depend | Dependent Conditions

GS2-Inbox

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on sending messages with stamp sheets
GS2-Key::Key Issuance of stamp sheets Dependent on attaching the reward to the message
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on setting multiple rewards for a message
GS2-Gateway::Namespace New Message Notification Dependent on setting up to receive push notifications using always-on communication sessions

GS2-Inventory

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on stamp sheet to grant items
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-JobQueue

Dependent Services Reasons to Depend Dependent Conditions
GS2-Gateway::Namespace Notification that a job has been registered Dependent on setting up to receive push notifications using always-on communication sessions

GS2-Key

Dependent Services Reasons to Depend Dependent Conditions

GS2-Limit

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on adding counters with stamp sheets

GS2-Lock

Dependent Services Reasons to Rely Dependent Conditions

GS2-Lottery

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on drawing lots with stamp sheets
GS2-Key::Key Issuance of stamp sheets Depends on when to draw lots
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on multiple rewards being set for rewards

GS2-Matchmaking

Dependent Services Reasons to Depend Dependent Conditions
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-Gateway::Namespace Matchmaking progress notification Dependent on setting up to receive push notifications using always-on communication sessions

GS2-Mission

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on operating counters with stamped sheets
GS2-Key::Key Issuance of stamp sheets Dependent on receiving achievement rewards
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on multiple rewards being set for rewards
GS2-Schedule::Event Set mission holding period Dependent on setting a task with a duration

GS2-Money

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on stamp sheet to add balance
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Quest

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on manipulating the clear flag on the stamp sheet
GS2-Key::Key Issuance of stamp sheets Dependent on when the quest start/completion process is executed
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on multiple rewards being set for rewards
GS2-Schedule::Event Set the quest release period. Dependent on setting up a quest with a publication period.

GS2-Ranking

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Depends on stamp sheet to register scores
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Realtime

Dependent Services Reasons to Depend Dependent Conditions
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Schedule

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on executing relative period event triggers

GS2-Script

Dependent Services Reasons to Depend Dependent Conditions
all Because GS2 SDK is available from within the script Dependent on using GS2 SDK from within a script

GS2-Showcase

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Issuance of stamp sheets Dependent on executing the product purchase process
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set
GS2-JobQueue::Namespace Used to award rewards when there is more than one reward Dependent on multiple rewards being set for rewards
GS2-Schedule::Event Set the product sales period Dependent on setting up a product with a sales period

GS2-Stamina

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Stamp sheet execution Dependent on manipulating stamina values on stamp sheets
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set

GS2-Version

Dependent Services Reasons to Depend Dependent Conditions
GS2-Key::Key Used for signature verification to validate version information received from the client Dependent on receiving version information from client and enabling signature verification
GS2-Script::Script Script Execution Dependent on setting scripts for events
GS2-JobQueue::Namespace Delayed execution of various registration completion scripts Dependent if a script is set for completion events and a job queue is set