NAV
Unity (UniTask) 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.

Please access the URL provided in the e-mail, verify your e-mail address, and 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. Select Create 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 the user. On the Credentials tab, click Create New Credential.
  6. On the Identifier > User List > User Information > Credential > Create new credential page, click Create 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

Adding users and credentials_ can be done from the GS2-Identifier administration screen, but is easier with GS2-Deploy.

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

For example, you can automatically add new users to GS2-Identifier by creating a stack with a template that adds a new user.

About Stacks

GS2-Deploy actually operates the resources of each service based on a template(which describes the procedures of how to operate and build the resources in GS2).
The aggregation of the resources built with this template is called a stack.

Reapplying a template with modified content to a stack will cause an update process to be performed.
The system detects differences in changes and automatically creates new resources that need to be created, updates resources that need to be updated, and deletes resources that need to be deleted.
This mechanism eliminates the need for developers to delete resources that are no longer needed, and allows for automatic construction simply by describing the desired resource status in a template.

Let's actually create a stack using template.

Example GS2-Deploy template for issuing credentials (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 shown is a sample Template that creates a user with the ApplicationAccess privilege.
You can change the user name created for the GS2-Identifier by changing the ApplicationUserName: application part.

Download Template

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

You can check the reflection status of the settings registered in the created stack in the Execution Status section of the stack.
After a few seconds, CREATE_COMPLETE is set and the credential setting is completed.

Select the Output tab after the reflection is complete, and you will see the Client ID and Client Secret of the Credential.
These values 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)

The zip file contains the sample source GS2AccountSample.cs PlayerPrefsAccountRepository.cs.
After creating a new project and installing GS2 SDK for Unity, extract the
Place the extracted GS2AccountSample.cs PlayerPrefsAccountRepository.cs file in the Scripts folder.
Create a game object in your scene and attach the GS2AccountSample component and the PlayerPrefs component.
PlayerPrefsAccountRepository.cs is an auxiliary utility that stores account information in PlayerPrefs.

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, 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

_profile = new Gs2.Unity.Util.Profile(
    clientId: clientId, // Client ID for credential
    clientSecret: clientSecret, // Client Secret for credential
    reopener: new Gs2BasicReopener() // Handler to reconnect
);

{
    var future = _profile.Initialize();

    yield return future;

    // If initialization fails, go to error processing
    if (future.Error != null)
    {
        OnError(future.Error);
        yield break;
    }
}

var gs2 = new Gs2.Unity.Core.Gs2Domain(_profile);
_profile = new Gs2.Unity.Util.Profile(
    clientId: clientId, // Client ID for credential
    clientSecret: clientSecret, // Client Secret for credential
    reopener: new Gs2BasicReopener() // Handler to reconnect
);

{
    var future = _profile.Initialize();

    yield return future;

    // If initialization fails, go to error processing
    if (future.Error != null)
    {
        OnError(future.Error);
        yield break;
    }
}

var gs2 = new Gs2.Unity.Core.Gs2Domain(_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.

Set the AccountNamespaceName KeyAccountAuthenticationKeyId similarly to the contents of the Output tab of the Account Management stack.

In the Unity component, set values for the following properties

The reopener is a handler to reconnect the communication.
Here we set Gs2BasicReopener which is pre-prepared in the library.

When the login process described below is executed using the utility class Profile, the access token can be automatically refreshed.

Create a new account

// Create new account

Debug.Log("Create new account");

var future = gs2.Account.Namespace(
    accountNamespaceName
).Create();

yield return future;

// Account creation failed
if (future.Error != null)
{
    OnError(future.Error);
    yield break;
}

// Retrieve created account information
var future2 = future.Result.Model();
yield return future2;

account = future2.Result;

// Save account information (EzAccount) in PlayerPrefs
_accountRepository.Save(account);
// Create new account

Debug.Log("Create new account");

var future = gs2.Account.Namespace(
    accountNamespaceName
).Create();

yield return future;

// Account creation failed
if (future.Error != null)
{
    OnError(future.Error);
    yield break;
}

// Retrieve created account information
var future2 = future.Result.Model();
yield return future2;

account = future2.Result;

// Save account information (EzAccount) in PlayerPrefs
_accountRepository.Save(account);
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 process

Debug.Log("Login process");

GameSession gameSession = null;

{
    var future = _profile.LoginFuture(
        new Gs2AccountAuthenticator(
            session: _profile.Gs2RestSession,
            accountNamespaceName: accountNamespaceName,
            keyId: accountEncryptionKeyId,
            userId: account.UserId,
            password: account.Password
        )
    );
    yield return future;
    if (future.Error != null)
    {
        OnError(future.Error);
        yield break;
    }

    // Create a GameSession object that holds an access token representing login status
    gameSession = future.Result;
}
// Login process

Debug.Log("Login process");

GameSession gameSession = null;

{
    var future = _profile.LoginFuture(
        new Gs2AccountAuthenticator(
            session: _profile.Gs2RestSession,
            accountNamespaceName: accountNamespaceName,
            keyId: accountEncryptionKeyId,
            userId: account.UserId,
            password: account.Password
        )
    );
    yield return future;
    if (future.Error != null)
    {
        OnError(future.Error);
        yield break;
    }

    // Create a GameSession object that holds an access token representing login status
    gameSession = future.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.
The accountNamespaceName is the namespace name in which the created account resides, and the keyId is the encryption key to be used to calculate the signature to be placed on the account's authentication result.
In addition, userId password is the user ID and password of the created account.

When the login process completes, an exception object is stored in future.Error in case of an error, and the result is stored in future.Result in case of success.

Resultcontains aGameSessionobject to represent the login state. From now on, when calling GS2 APIs, you should 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");

{
    var it = gs2.Account.Namespace(
        accountNamespaceName
    ).Me(
        gameSession
    ).TakeOvers();

    var takeOverModels = new List<EzTakeOver>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            if (it.Error is BadRequestException || it.Error is NotFoundException)
            {
                OnError(it.Error);
                break;
            }

            OnError(new CanIgnoreException(it.Error));
            break;
        }

        if (it.Current != null)
        {
            takeOverModels.Add(it.Current);
        }
    }

    foreach (var takeOverModel in takeOverModels)
    {
        // Information about the takeover is retrieved.
    }
}
// Get list of takeover information

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

{
    var it = gs2.Account.Namespace(
        accountNamespaceName
    ).Me(
        gameSession
    ).TakeOvers();

    var takeOverModels = new List<EzTakeOver>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            if (it.Error is BadRequestException || it.Error is NotFoundException)
            {
                OnError(it.Error);
                break;
            }

            OnError(new CanIgnoreException(it.Error));
            break;
        }

        if (it.Current != null)
        {
            takeOverModels.Add(it.Current);
        }
    }

    foreach (var takeOverModel in takeOverModels)
    {
        // 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.

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;
}
// 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.Exception;
using Gs2.Unity.Core.Exception;
using Gs2.Unity.Gs2Account.Model;
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;

    private PlayerPrefsAccountRepository _accountRepository;

    private Profile _profile;

    // Start is called before the first frame update
    void Start()
    {
        _accountRepository = GetComponentInParent<PlayerPrefsAccountRepository>() ?? GetComponent<PlayerPrefsAccountRepository>();

        StartCoroutine(CreateAndLoginAction());
    }

    public IEnumerator CreateAndLoginAction()
    {
        // Initialize GS2 SDK

        Debug.Log("Initialize GS2 SDK");

        _profile = new Gs2.Unity.Util.Profile(
            clientId: clientId, // Client ID for credential
            clientSecret: clientSecret, // Client Secret for credential
            reopener: new Gs2BasicReopener() // Handler to reconnect
        );

        {
            var future = _profile.Initialize();

            yield return future;

            // If initialization fails, go to error processing
            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Core.Gs2Domain(_profile);

        // Retrieve stored account information (EzAccount) from PlayerPrefs
        EzAccount account = _accountRepository.Load();

        if (account == null)
        {
            // Create new account

            Debug.Log("Create new account");

            var future = gs2.Account.Namespace(
                accountNamespaceName
            ).Create();

            yield return future;

            // Account creation failed
            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }

            // Retrieve created account information
            var future2 = future.Result.Model();

            yield return future2;

            account = future2.Result;

            // Save account information (EzAccount) in PlayerPrefs
            _accountRepository.Save(account);
        }

        // Login process

        Debug.Log("Login process");

        GameSession gameSession = null;

        {
            var future = _profile.LoginFuture(
                new Gs2AccountAuthenticator(
                    session: _profile.Gs2RestSession,
                    accountNamespaceName: accountNamespaceName,
                    keyId: accountEncryptionKeyId,
                    userId: account.UserId,
                    password: account.Password
                )
            );

            yield return future;

            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }

            // Create a GameSession object that holds an access token representing login status
            gameSession = future.Result;
        }

        // Get list of takeover information

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

        {
            var it = gs2.Account.Namespace(
                accountNamespaceName
            ).Me(
                gameSession
            ).TakeOvers();

            var takeOverModels = new List<EzTakeOver>();
            while (it.HasNext())
            {
                yield return it.Next();
                if (it.Error != null)
                {
                    if (it.Error is BadRequestException || it.Error is NotFoundException)
                    {
                        OnError(it.Error);
                        break;
                    }

                    OnError(new CanIgnoreException(it.Error));
                    break;
                }

                if (it.Current != null)
                {
                    takeOverModels.Add(it.Current);
                }
            }

            foreach (var takeOverModel in takeOverModels)
            {
                // 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()
    {

    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using Gs2.Core.Exception;
using Gs2.Unity.Core.Exception;
using Gs2.Unity.Gs2Account.Model;
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;

    private PlayerPrefsAccountRepository _accountRepository;

    private Profile _profile;

    // Start is called before the first frame update
    void Start()
    {
        _accountRepository = GetComponentInParent<PlayerPrefsAccountRepository>() ?? GetComponent<PlayerPrefsAccountRepository>();

        StartCoroutine(CreateAndLoginAction());
    }

    public IEnumerator CreateAndLoginAction()
    {
        // Initialize GS2 SDK

        Debug.Log("Initialize GS2 SDK");

        _profile = new Gs2.Unity.Util.Profile(
            clientId: clientId, // Client ID for credential
            clientSecret: clientSecret, // Client Secret for credential
            reopener: new Gs2BasicReopener() // Handler to reconnect
        );

        {
            var future = _profile.Initialize();

            yield return future;

            // If initialization fails, go to error processing
            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Core.Gs2Domain(_profile);

        // Retrieve stored account information (EzAccount) from PlayerPrefs
        EzAccount account = _accountRepository.Load();

        if (account == null)
        {
            // Create new account

            Debug.Log("Create new account");

            var future = gs2.Account.Namespace(
                accountNamespaceName
            ).Create();

            yield return future;

            // Account creation failed
            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }

            // Retrieve created account information
            var future2 = future.Result.Model();

            yield return future2;

            account = future2.Result;

            // Save account information (EzAccount) in PlayerPrefs
            _accountRepository.Save(account);
        }

        // Login process

        Debug.Log("Login process");

        GameSession gameSession = null;

        {
            var future = _profile.LoginFuture(
                new Gs2AccountAuthenticator(
                    session: _profile.Gs2RestSession,
                    accountNamespaceName: accountNamespaceName,
                    keyId: accountEncryptionKeyId,
                    userId: account.UserId,
                    password: account.Password
                )
            );

            yield return future;

            if (future.Error != null)
            {
                OnError(future.Error);
                yield break;
            }

            // Create a GameSession object that holds an access token representing login status
            gameSession = future.Result;
        }

        // Get list of takeover information

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

        {
            var it = gs2.Account.Namespace(
                accountNamespaceName
            ).Me(
                gameSession
            ).TakeOvers();

            var takeOverModels = new List<EzTakeOver>();
            while (it.HasNext())
            {
                yield return it.Next();
                if (it.Error != null)
                {
                    if (it.Error is BadRequestException || it.Error is NotFoundException)
                    {
                        OnError(it.Error);
                        break;
                    }

                    OnError(new CanIgnoreException(it.Error));
                    break;
                }

                if (it.Current != null)
                {
                    takeOverModels.Add(it.Current);
                }
            }

            foreach (var takeOverModel in takeOverModels)
            {
                // 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 project name as appropriate.

// 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 cryptographic key used to compute the signature to be assigned to 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);

}

GS2 YouTube Channel

Videos explaining how to use Game Server Services and its features are available on the following channels.

Game Server Services EN

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

Retrieving from Maven

You can retrieve packages from Maven.

gs2-java-sdk

GS2-PHP-SDK

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

Retrieving with Composer

Installing GS2-PHP-SDK

composer require gs2/gs2-php-sdk

You can retrieve the package with Composer.

gs2-php-sdk

GS2-Golang-SDK

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

GS2-Python-SDK

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

Retrieving with PyPI

Installing GS2-Python-SDK

pip install gs2

You can retrieve packages from the Python Package Index (PyPI).

gs2-cdk

GS2-Typescript-SDK

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

Retrieval by npm

Installing GS2-Typescript-SDK

npm i gs2-cdk

Packages can be obtained from npm.

gs2-cdk

GS2-CSharp-SDK

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

Retrieved from NuGet

You can get the package from NuGet.

GS2.CSharp.Sdk

GS2 CDK

CDK stands for Cloud Development Kit, a development kit to enable GS2 orchestration with code.
To explain the functionality more concretely, you can write code to instantiate an object corresponding to a GS2 resource in the CDK and call the dump API to generate a GS2-Deploy template.
GS2-Deploy templates can be written in YAML format, but since YAML files are not program code, it is not possible to import external files or execute loops, and to optimize the workflow, writing code to generate templates was This was required to optimize the workflow.
CDK is a solution to optimize such a workflow, allowing the generation of GS2-Deploy templates while parsing master data Excel files and defining event durations in loops within the tool using CDK.

First, let's look at a template file that defines a simple GS2 credential.

import core from "gs2cdk/core";
import identifier from "gs2cdk/identifier";

class IdentifierForApplicationStack extends core.Stack {

    public constructor() {
        super();

        let identifier_resource = new identifier.model.User(
            this,
            "App".
        ).attachGrn(
            identifier.model.SecurityPolicy.ApplicationAccessGrn()
        ).identifier();

        this.output(
            "ClientId",
            identifier_resource.getAttrClientId().str()
        );
        this.output(
            "ClientSecret",
            identifier_resource.getAttrClientSecret().str()
        );
    }
}

This will create a user named App, grant "ApplicationAccess" privileges, and generate credentials.
It will then record the issued ClientId and ClientSecret.

console.log(new IdentifierForApplicationStack().yaml());

This code will output the GS2-Deploy template.

GS2TemplateFormatVersion: "2019-05-01"
Resources:
  Identifier_User_App:
    Type: GS2::Identifier::User
    Properties:
      Name: App
    DependsOn: [].
  Identifier_AttachSecurityPolicy_App:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: App
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - Identifier_User_App
  Identifier_Identifier_:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: App
    DependsOn:
      - Identifier_User_App
Outputs:
  ClientId: !GetAttr Item.
  ClientSecret: !GetAttr ClientSecret

The output is as above.
You can write this result to a file and upload it from the management console or use GS2-SDK to reflect it in GS2-Deploy to build your environment.

GS2-Java-CDK

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

Acquisition by Maven

You can get the package from Maven.

gs2-java-cdk

GS2-PHP-CDK

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

Retrieved from #### Composer

Installing GS2-PHP-CDK

composer require gs2/gs2-php-cdk

You can retrieve the package with Composer.

gs2-php-cdk

GS2-Golang-CDK

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

GS2-Python-CDK

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

Retrieved from #### PyPI

Installing GS2-Python-CDK

pip install gs2cdk

You can retrieve packages from the Python Package Index (PyPI).

gs2

GS2-Typescript-CDK

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

Retrieved from #### npm

Installing GS2-Typescript-CDK

npm i gs2

You can get the package from npm.

gs2

GS2-CSharp-CDK

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

Getting from NuGet

You can get the package from NuGet.

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 only the processing (including login processing) necessary to perform version checking (GS2-Version)

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

Example of policy document format (JSON)

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

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.

“Actions”

Example of specifying Actions (JSON)

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

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.

Enumeration of actions

Example of enumerating methods in Actions (JSON)

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

"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).

“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

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

A template consists of the following sections

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

Example of Alias attribute definition (YAML)

Globals:
  Alias:
    AccountNamespaceName: game-0001

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 replacement specification: ${AccountNamespaceName}

Resources section

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}

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

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

Outputs section (YAML)

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

Define output values to be displayed in the management console.

!GetAttr tag

Example of !GetAttr tag usage (YAML)

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

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

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-Script GS2 Service Extension

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

-- Get model information from argument
inventory_namespaceName = 'inventory-0001'
userId = args.account.userId
inventoryName = 'inventory'
itemName = 'item-0001'
acquireCount = 1
expiresAt = 0
itemSetName = ''

inventory_client = gs2('inventory')

-- issue a request
result = inventory_client.acquire_item_set_by_user_id({
    namespaceName=inventory_namespaceName,
    inventoryName=inventoryName,
    itemName=itemName,
    userId=userId,
    acquireCount=acquireCount,
    expiresAt=expiresAt,
    createNewItemSet=nil,
    itemSetName=itemSetName,
})

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

result = {}

GS2 is designed so that a game system can be built with only standard features for general use.
However, depending on the game specifications, there may be some things that cannot be realized with the standard GS2 functions.

GS2 supports script extensions written in the Lua language to handle such cases. GS2-Account can be used for when creating a new account when authenticating an account when registering a takeover setting when executing a takeover and so on. when transferring the account.
This allows us to meet the needs such as I want to send rewards to the gift box when I set up the transfer. This is to meet the needs ofdelivery of rewards to the gift box when a handover is set up.

If you want to be able to register a transfer multiple times and receive rewards as many times as you want, it would break the game system. If you want to be able to give a reward only once, you can implement it in combination with the number of times limit function provided by GS2-Limit, for example. If you want to be able to grant a reward only once, please be creative in your scripts.

Configuration in the Management Console

Event Trigger Settings

Configuration of event triggers can be done from the script section of the namespace list > namespace information > namespace update page for each service in the Management Console.

Script Configuration

Script configuration is done from the Script > Namespace List > Namespace Information > Create New Script page of the GS2-Script service in the Management Console.

Parameters necessary for test execution can be passed in JSON format as arguments.
The structure of the parameters should be adapted accordingly to the structure of the argument model.

Example of passing arguments for test execution (JSON)

{
  "namespace": {
    "namespaceId": "grn:gs2:ap-northeast-1:xxxxxxxx-xxxxxxxxxxx:account:account-0001",
    "name": "account-0001"
  },
  "account": {
    "accountId": "grn:gs2:ap-northeast-1:xxxxxxxx-xxxxxxxxxxx:account:account-0001:account:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "userId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}

Utility Methods

Extension methods available in GS2-Script extension scripts (Lua language).

util.table_to_json

Example implementation (Lua)

result = util.table_to_json({a="a", b=1, c=false})
if result.isError then
  fail(result['statusCode'], result['errorMessage'])
end
json_str = result["result"]

Execution Result.

{"a":"a","b":1,"c":false}

Convert a Lua table type (array) to a string in JSON format.

Request
Type Description
table table table
Result
Type Description
isError bool Is an error occurring
statusCode int status code
errorMessage string Error message
result string JSON string of the conversion result

util.json_to_table

Example Implementation (Lua)

result = util.json_to_table("{\"a\": \"a\", \"b\": 1, \"c\": false}")
if result.isError then
  fail(result['statusCode'], result['errorMessage'])
end
json_table = result["result"]

Convert a string in JSON format to a Lua table type (array).

Request
type description
jsonText string JSON format string
Result
Type Description
isError bool Is an error occurring
statusCode int status code
errorMessage string Error message
result Lua table type Lua table of the conversion result

util.split

Example implementation (Lua)

result = util.split("a,b,c", ",")
if result.isError then
  fail(result['statusCode'], result['errorMessage'])
end
split_table = result["result"]
print(split_table[1])
print(split_table[2])
print(split_table[3])

result

a
b
c

Split a string.

Request
Type Description
value string original string
sep string delimiter, delimited string
Result
Type Description
isError bool Is an error occurring
statusCode int status code
errorMessage string Error message
result Lua table type Lua table of split strings

http.get

Example implementation (Lua)

result = http.get("https://example.com")
if result.isError then
  fail(result['statusCode'], result['errorMessage'])
end
get_result = result["result"]

Issue an HTTP GET request.

Request
Type Description
url string URL to connect to
Result
Type Description
isError bool Is an error occurring
statusCode int status code
errorMessage string Error message
result string HTTP response body

http.post

Example Implementation (Lua)

result = http.post("https://example.com", "application/json", "{}")
if result.isError then
  fail(result['statusCode'], result['errorMessage'])
end
post_result = result["result"]

Issue an HTTP POST request.

Request
Type Description
url string URL to connect to
contentType string Content-Type of the HTTP header
body string body of HTTP request message
Result
Type Description
isError bool Is an error occurring
statusCode int status code
errorMessage string Error message
result string HTTP response body

Tips:Execution timing and speeding up of event triggers

There are two types of event triggers that can be executed at two different times.
One is a trigger that executes a script before the target event is executed and can affect the contents of the target event based on the results of the script execution, and the other is a trigger that executes a script after the processing of the target event is complete.
When a script is executed before the event occurs, the script execution and its target event are processed in sequence, so the waiting time for the target event to complete is equal to the script + event execution time.
If the result of script processing changes what the target event executes, or if there is no need to wait for script processing, setting the trigger to execute the script after completion will execute the script without affecting the waiting time for the target event to complete, thus reducing the waiting processing for the target event. This will not affect the waiting time for the target event to complete.

Stamp Sheet Overview

GS2 has a system called stamp sheet, which is used to coordinate processing among services within GS2.
We believe that the use of stamp sheets will be indispensable for the use of GS2.
You may read this section now or refer to it when you actually use stamp sheets.

For example, by combining GS2-Money, which handles currency, and GS2-Inventory, which handles in-game items, a stamp sheet can be used to purchase items with the currency.
If a request to spend currency is sent to GS2-Money and a request to acquire items is sent to GS2-Inventory separately, there is a possibility that only one of the requests will be processed if the application stops in the middle of the process or due to cheating.

On the other hand, a stamp sheet combines a spend action (in this case, spend of billed currency) and an acquisition action (in this case, acquisition of an item) into one.
In this example, the item is purchased with the charged currency, so the item is registered in the product master of GS2-Showcase, which realizes the product in the game.
We will register a stamp sheet to be issued upon purchase of the item.

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.

Although the purchase of items is introduced here as an example, many other situations can be envisioned where stamp sheets can be used, such as acquiring items to complete quests by consuming stamina in GS2-Quest.

It is also possible to set 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 is to avoid a chain reaction that would prevent the use of related services if the server managing the rewards is down when the rewards are given.
For such cases, we provide a mechanism that registers the reward processing to GS2-JobQueue at the time of stamp sheet execution and allows retries even if the execution of the reward processing fails once.

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);
    }

    // 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
    }
    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.

How to use UIKit

UIKit has two types of prefabrication for different functions.

In addition, each component in a prefab has the following functions.

Component Function
Fetcher component retrieves and retains information from GS2 services
View component Reflects property values in the UI.
Enabler component Controls activation/deactivation of a target GameObject according to its condition.
Action component Performs various actions.

How to add UI

Create a new project in Unity and place a prefab GS2.prefab in the hierarchy for initializing GS2.

Procedure for setting up Gs2.prefab

  1. Create a Core/Environment/Gs2Environment ScriptableObject and set credential information from the management console.
    Create > Game Server Services > Core > Environment
  2. Register a reference to the created Gs2Environment ScriptableObject in the Environment of the Gs2ClientHolder component.
  3. To use the GS2-Distributor functionality, generate a Gs2Distributor/Namespace ScriptableObject and set the namespace name.
  4. Create a Gs2Distributor/Namespace ScriptableObject and set the namespace name.
    Create > Game Server Services > Gs2Distributor > Namespace
  5. Register a reference to the Gs2Distributor NameSpace ScriptableObject you created in the Distributor Namespace of the Gs2ClientHolder component.

Instructions for setting up Gs2AccountAutoLogin.prefab

  1. create a GS2Account/NameSpace ScriptableObject and set the Namespace Name property to the namespace name of the GS2-Account.
    Create > Game Server Services > GS2Account > Namespace.
  2. Register a reference to the GS2Account/NameSpace ScriptableObject created in step 1 in the Namespace property of the Gs2AccountAccountCreateAction component.
  3. In the Namespace property of the Gs2ProfileLoginAction component, register a reference to the GS2Account/NameSpace ScriptableObject you created.
  4. Create a Gs2Key/NameSpace ScriptableObject and set the Namespace Name to the namespace name of the GS2-Key.
    Create > Game Server Services > Gs2Key > Namespace.
  5. Create a Gs2Key/Key ScriptableObject and register a reference to the Gs2Key/NameSpace ScriptableObject created in step 4 in its Namespace property.
    Set the Key Name property to the encryption key name of the GS2-Key key entity. Create > Game Server Services > Gs2Key > Key.
  6. Register a reference to the Gs2Key/Key ScriptableObject created in step 5 in the Key of the Gs2ProfileLoginAction component.

Placement of UI display prefab

Place a Canvas on the hierarchy and place a GS2 UIKit UI display prefab.
Here is an example of the UI display for Stamina.

Place Gs2StaminaStaminaPrefab as a child of Canvas.

Set up Gs2StaminaStaminaPrefab to access GS2-Stamina.

  1. create a Gs2Stamina/NameSpace ScriptableObject and set the Namespace Name to the namespace name of GS2-Stamina.
    Create > Game Server Services > Gs2Stamina > Namespace.
  2. create a Gs2Stamina/Stamina ScriptableObject and register a reference to the created Gs2Key/NameSpace ScriptableObject in the Namespace.
    Set the Stamina Name to the name of the stamina model.
    Create > Game Server Services > Gs2Stamina > Stamina
  3. Register a reference to the Gs2Stamina/Stamina ScriptableObject you created in the Stamina of the Gs2StaminaStaminaFetcher component.

With the settings made so far, stamina will be displayed in the UI when the game is played.

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.10.1

Download the sample package file from above.
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.

GS2 UIKit Sample GitHub Repository

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

Deploy 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

USD 0.0002 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)

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

Debug.Log(Item.UserId); // user ID
Debug.Log(Item.Password); // Password
Debug.Log(Item.CreatedAt); // Creation date and time
var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // namespace name
);
var future = domain.Create(
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(Item.UserId); // user ID
Debug.Log(Item.Password); // Password
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

Registration of transfer settings Implementation example (Unity)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // 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.UserId); // User ID
Debug.Log(Item.Type); // slot number
Debug.Log(Item.UserIdentifier); // User ID for transfer
Debug.Log(Item.CreatedAt); // Creation date and time
var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).TakeOver(
    type: 0 // slot number
);
var future = domain.AddTakeOverSetting(
    userIdentifier: "user-0001@gs2.io", // user ID for takeover
    password: "password-0001" // password
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

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

Implementation example of takeover execution (Unity)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // 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(item.UserId); // user ID
Debug.Log(item.Password); // password
Debug.Log(item.CreatedAt); // Creation date and time
var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // namespace name
);
var future = domain.DoTakeOver(
    type: 0, // slot number
    userIdentifier: "user-0001@gs2.io", // user ID for takeover
    password: "password-0001" // password
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result.UserId); // user ID
Debug.Log(result.Password); // password
Debug.Log(result.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)

var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).WebSocketSession(
);
var result = await domain.SetUserIdAsync(
    allowConcurrentAccess: false // Do you 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
var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).WebSocketSession(
);
var future = domain.SetUserId(
    allowConcurrentAccess: false // Do you allow connections from different clients at the same time?
);
yield return future;
if (future.Error != null)
{
    OnError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    OnError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

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

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)

var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // 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(item.UserId); // user ID
Debug.Log(item.Password); // password
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(body); // Account information to be signed
Debug.Log(signature); // Signature
var domain = gs2.Account.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Account(
    userId: "user-0001" // account ID
);
var future = domain.Authentication(
    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 future;
if (future.Error != null)
{
    OnError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    OnError.Invoke(future2.Error, null);
    yield break;
}
var item = future2.Result;
var body = future.Result.Body;
var signature = future.Result.Signature;

Debug.Log(item.UserId); // user ID
Debug.Log(item.Password); // password
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(body); // Account information to be signed
Debug.Log(signature); // Signature

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

var domain = gs2.Auth.AccessToken(
);
var result = await domain.LoginAsync(
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace-0001:key:key-0001", // GRN of the encryption key used to create the signature
    body: "body", // Account credentials to be signed
    signature: "signature" // signature
);
var token = result.Token;
var userId = result.UserId;
var expire = result.Expire;

Debug.Log(token); // access token
Debug.Log(userId); // user ID
Debug.Log(expire); // Expiration date
var domain = gs2.Auth.AccessToken();
var future = domain.Login(
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace-0001: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 future;
if (future.Error != null)
{
    OnError.Invoke(future.Error, null);
    yield break;
}
var token = future.Result.Token;
var userId = future.Result.UserId;
var expire = future.Result.Expire;

Debug.Log(token); // access token
Debug.Log(userId); // user ID
Debug.Log(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.

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

USD 0.0002 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

USD 0.0002 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

USD 0.0002 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. request GS2 with management information such as data name and access rights, and retrieve URL for uploading to the file server.
2. upload data to the retrieved URL using an HTTP client.
3. report to GS2 that the upload is 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.

Get URL for upload Implementation example (Unity)

var domain = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // 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 ID 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

var domain = gs2.Datastore.Namespace(
"namespace-0001" // namespace name ).Me(
GameSession // GameSession object (access token) ); var future = domain.PrepareUpload(
name: "dataObject-0001", // name of data
scope: "public", // file access rights
allowUserIds: new string[] { }, // User ID list to be published
updateIfExists: null // if data already exists, raise an error or update the data ); yield return future; if (future.Error != null) {
throw future.Error; } var future2 = future.Result.Model(); yield return future2; if (future2.Error != null) {
throw future2.Error; } var result = future2.Result; var uploadUrl = future.Result.UploadUrl; Assert.NotNull(result);

Debug.Log(result.DataObjectId); // data object ID Debug.Log(result.Name); // Name of data Debug.Log(result.UserId); // user ID Debug.Log(result.Scope); // File access rights Debug.Log(result.AllowUserIds); // User ID list to be published Debug.Log(result.Status); // status Debug.Log(result.Generation); // Data generation Debug.Log(result.CreatedAt); // Creation date and time Debug.Log(result.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)

var domain = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // 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 ID 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

var domain = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession object (access token) ).DataObject(
dataObjectName: "dataObject-0001" // data name ); var future = domain.DoneUpload( ); yield return future; if (future.Error != null) {
OnError.Invoke(future.Error, null);
yield break; } var future2 = future.Result.Model(); yield return future2; if (future2.Error != null) {
OnError.Invoke(future2.Error, null);
yield break; } var result = future2.Result;

Debug.Log(result.DataObjectId); // data object ID Debug.Log(result.Name); // Name of data Debug.Log(result.UserId); // user ID Debug.Log(result.Scope); // File access rights Debug.Log(result.AllowUserIds); // User ID list to be published Debug.Log(result.Status); // status Debug.Log(result.Generation); // Data generation Debug.Log(result.CreatedAt); // Creation date and time Debug.Log(result.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 example (Unity)

var result = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession Session object representing login state ).UploadAsync(
scope: "public", // file access rights
allowUserIds: new List<string>(), // list of user IDs to be published
data: new byte[] {0x00, 0x01, 0x02} // binary data in byte array );

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

var future = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession Session object representing login state ).Upload(
scope: "public", // file access rights
allowUserIds: new List<string>(), // list of user IDs to be published
data: new byte[] {0x00, 0x01, 0x02} // binary data in byte array ); yield return future; var result = future.Result;

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

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)

var domain = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // 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 ID 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

var domain = gs2.Datastore.Namespace(
namespaceName: "namespace-0001" // namespace name ).User(
userId: "user-0001" // user ID ).DataObject(
dataObjectName: "dataObject-0001" // Data name ); var future = domain.PrepareDownloadByUserIdAndDataObjectName( ); yield return future; if (future.Error != null) {
OnError.Invoke(future.Error, null);
yield break; } var future2 = future.Result.Model(); yield return future2; if (future2.Error != null) {
OnError.Invoke(future2.Error, null);
yield break; } var result = future2.Result; var fileUrl = future.Result.FileUrl; var contentLength = future.Result.ContentLength;

Debug.Log(item.DataObjectId); // data object ID 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

USD 0.0002 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

USD 0.0002 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

USD 0.0002 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

USD 0.0002 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

USD 0.0002 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)

var domain = gs2.Exchange.Namespace(
    namespaceName: "namespace-0001" // 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)
);

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet used to execute the exchange process
var domain = gs2.Exchange.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Exchange(
);
var future = domain.Exchange(
    rateName: "rate-0001", // Name of exchange rate type
    count: 1, // Number of lots to be exchanged
    config: null // config value (optional value)
);
yield return future;
if (future.Error != null)
{
    OnError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet used to execute the exchange process

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'.

Also, if multiple rewards are to be set for a single exchange model, it must be linked to 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

USD 0.0002 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

GS2-Experience is not concerned with the following features

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 "-sword" or "-bow" to the back of GS2-Inventory's "possession ID" to specify the property ID. string behind the "possession ID" in GS2-Inventory to distinguish between property IDs.

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)

var domain = gs2.Experience.Namespace(
namespaceName: "namespace-0001" // 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

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

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

This service is designed to realize equipment and partying 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

USD 0.0002 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: "namespace-0001" // 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:namespace-0001:key:key-0001" // cryptographic key GRN of the GS2-Key used to issue the signature
);
var items = await result.ModelAsync();
var body = result.Body;
var signature = result.Signature;

Debug.Log(items); // Item possession quantity list by expiration date
Debug.Log(body); // Item Set Information for Signature Subject
Debug.Log(signature); // signature
Debug.Log(result.OverflowCount); // Quantity of items transferred to GS2-Inbox that were not received beyond the possession limit
var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // 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 future = domain.GetItemWithSignature(
    keyId: "grn:gs2:ap-northeast-1:owner_id:key:namespace-0001:key:key-0001" // cryptographic key GRN of the GS2-Key used to issue the signature
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;
var body = future.Result.Body;
var signature = future.Result.Signature;

Debug.Log(items); // Item possession quantity list by expiration date
Debug.Log(body); // Item Set Information for Signature Subject
Debug.Log(signature); // signature
Debug.Log(result.OverflowCount); // Quantity of items transferred to GS2-Inbox that were not received beyond the possession limit

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.

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
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

Save the form in the form storage area (Mold)

Example of creating a list of signed slots (Unity)

var domain = gs2.Formation.Namespace(
    namespaceName: "namespace-0001" // 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[]
    {
        new 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:namespace-0001:key:key-0001" // GRN of the cryptographic key used to issue the signature
);
var item = await result.ModelAsync();

Debug.Log(item.Name); // name of form save area
Debug.Log(item.Index); // index of the storage area
Debug.Log(item.Slots); // Slot list
var domain = gs2.Formation.Namespace(
    namespaceName: "namespace-0001" // 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 future = domain.SetForm(
    slots: new [] {
        new 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:namespace-0001:key:key-0001" // GRN of the cryptographic key used to issue the signature
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(item.Name); // name of form save area
Debug.Log(item.Index); // index of the storage area
Debug.Log(item.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

USD 0.0002 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)

var domain = gs2.Friend.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Friend.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Profile(
);
var future = domain.UpdateProfile(
    publicProfile: "public", // public profile (optional)
    followerProfile: "follower", // public profile for followers (optional)
    friendProfile: "friend" // public profile for friends (optional)
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

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

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)

var domain = gs2.Friend.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).FollowUser(
    targetUserId: "user-0002", // User ID to follow
    withProfile: true // whether to retrieve the profile together
);
var result = await domain.FollowAsync(
);
var item = await result.ModelAsync();

Debug.Log(item.UserId); // user ID
var domain = gs2.Friend.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).FollowUser(
    targetUserId: "user-0002", // User ID to follow
    withProfile: true // whether to retrieve the profile together
);
var future = domain.Follow(
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result.UserId); // user ID

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

USD 0.0002 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)

var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Gateway.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).WebSocketSession(
);
var future = domain.SetUserId(
    allowConcurrentAccess: null // allow connections from different clients at the same time?
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

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

After the login process is completed at the client, the user ID is registered with GS2-Gateway so that the user can receive push notifications.

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
# Store result in result

Define what to do when you receive a push notification

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

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

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
        }
    }
}
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
        }
    }
}

Register a destination to call when you receive a push notification (Unity)

gs2Client.profile.Gs2Session.OnNotificationMessage += PushNotificationHandler;
gs2Client.profile.Gs2Session.OnNotificationMessage += PushNotificationHandler;

Set the defined function as the destination to be called when a push notification arrives.

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

USD 0.0002 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 (JSON)
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() // Handler to reconnect
);

{
    var future = profile.Initialize();

    yield return future;
{

var gs2 = new Gs2.Unity.Core.Gs2Domain(profile); // Various APIs can be called using gs2 (Gs2.Unity.Core.Gs2Domain)
var profile = new Gs2.Unity.Util.Profile(
    clientId: 'credential ID',
    clientSecret: 'credential password',
    reopener: new Gs2BasicReopener() // Handler to reconnect
);

{
    var future = profile.Initialize();

    yield return future;
{

var gs2 = new Gs2.Unity.Core.Gs2Domain(profile); // Various APIs can be called using gs2 (Gs2.Unity.Core.Gs2Domain)

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

USD 0.0002 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)

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

Debug.Log(items); // List of messages
AsyncResult<EzListResult> asyncResult = null;
var current = gs2.Inbox.List(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace-0001", // 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: "namespace-0001" // 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: "namespace-0001" // 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: "namespace-0001" // 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
AsyncResult<EzReadResult> asyncResult = null;
var current = gs2.Inbox.Read(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace-0001", // 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.

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

USD 0.0002 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)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Inventory(
    inventoryName: "inventory-0001" // Inventory type name
);
var future = domain.Model();
yield return future;
var item = future.Result;

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)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Inventory(
    inventoryName: "item" // name of inventory type
);
var it = domain.ItemSets(
);
List<EzItemSet> items = new List<EzItemSet>();
while (it.HasNext())
{
    yield return it.Next();
    if (it.Error != null)
    {
        onError.Invoke(it.Error, null);
        break;
    }
    if (it.Current != null)
    {
        items.Add(it.Current);
    }
    else
    {
        break;
    }
}

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

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)

var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // 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();

Debug.Log(items); // List of item possession quantities by expiration date after consumption
Debug.Log(items[0].ItemSetId); // inventory model name
Debug.Log(items[0].Name); // name of item model type
Debug.Log(items[0].InventoryName); // inventory model name
Debug.Log(items[0].ItemName); // name of item model
Debug.Log(items[0].Count); // quantity in possession
Debug.Log(items[0].SortValue); // display order
Debug.Log(items[0].ExpiresAt); // Expiration date
var domain = gs2.Inventory.Namespace(
    namespaceName: "namespace-0001" // 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 future = domain.Consume(
    consumeCount: 1L // volume to consume
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result); // List of item possession quantities by expiration date after consumption
Debug.Log(result[0].ItemSetId); // inventory model name
Debug.Log(result[0].Name); // name of item model type
Debug.Log(result[0].InventoryName); // inventory model name
Debug.Log(result[0].ItemName); // name of item model
Debug.Log(result[0].Count); // quantity in possession
Debug.Log(result[0].SortValue); // display order
Debug.Log(result[0].ExpiresAt); // Expiration date

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

USD 0.0002 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 Legacy)

AsyncResult<EzRunResult> asyncResult = null;
var current = gs2.JobQueue.Run(
    callback: r => { asyncResult = r; },
    session: session, // GameSession object (access token)
    namespaceName: "namespace-0001" // 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

USD 0.0002 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

USD 0.0002 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)

var domain = gs2.Limit.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Limit.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Counter(
    limitName: "daily", // the frequency limit type name
    counterName: "counter1" // counter name
);
var future = domain.CountUp(
    countUpValue: 1, // amount to count up (optional)
    maxValue: 100 // maximum value allowed to count up (optional)
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

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)

var domain = gs2.Limit.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Limit.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Counter(
    limitName: "daily", // the frequency limit type name
    counterName: "counter1" // counter name
);
var future = domain.Model();
yield return future;
var item = future.Result;

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

USD 0.0002 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)

var domain = gs2.Lock.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Lock.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Mutex(
    propertyId: "property-0001" // property ID
);
var future = domain.Lock(
    transactionId: "transaction-0001", // transaction ID to acquire lock
    ttl: 100000L // Expiration time to acquire lock (seconds)
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result.MutexId); // Mutex GRN
Debug.Log(result.PropertyId); // property ID
Debug.Log(result.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)

var domain = gs2.Lock.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Lock.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Mutex(
    propertyId: "property-0001" // property ID
);
var future = domain.Unlock(
    transactionId: "transaction-0001" // Transaction ID for which the lock was acquired
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    throw future2.Error;
}
var result = future2.Result;

Debug.Log(result.MutexId); // Mutex GRN
Debug.Log(result.PropertyId); // property ID
Debug.Log(result.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

USD 0.0002 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

USD 0.0002 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.

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 list of user IDs that are allowed to participate.
This can be used to limit the number of participants by specifying 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

USD 0.0002 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 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 (Unity)

var domain = gs2.Matchmaking.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
);
var result = await domain.CreateGatheringAsync(
    player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer
    {
        Attributes = new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttribute>
        {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute
            {
                Name = "stage",
                Value = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute
            {
                Name = "level",
                Value = 10,
            }
        },
    }, // Own player information
    attributeRanges: new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange[]
    {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange
        {
            Name = "stage",
            Min = 1,
            Max = 1,
        },
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange
        {
            Name = "level",
            Min = 0,
            Max = 10,
        }
    }, // application limit
    capacityOfRoles: new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole[]
    {
        new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole
        {
            RoleName = "default",
            Capacity = 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.ExpiresAt); // Gathering expiration date
Debug.Log(item.CreatedAt); // Creation date and time
Debug.Log(item.UpdatedAt); // Last updated
var domain = gs2.Matchmaking.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
);
var future = domain.CreateGathering(
    player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer
    {
        Attributes = new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttribute
        {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute()
            {
                Name = "stage",
                Value = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute()
            {
                Name = "level",
                Value = 10,
            }
        },
    }, // Own player information
    attributeRanges: new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange[]
    {
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
        {
            Name = "stage",
            Min = 1,
            Max = 1,
        },
        new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange()
        {
            Name = "level",
            Min = 0,
            Max = 10,
        }
    }, // application limit
    capacityOfRoles: new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole[]
    {
        new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole()
        {
            RoleName = "default",
            Capacity = 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)
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}

var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}

var result = future2.Result;

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.ExpiresAt); // Gathering expiration date
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)

var domain = gs2.Matchmaking.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession object (access token) ); var items = await domain.DoMatchmakingAsync(
new EzPlayer
{
RoleName = "attacker",
} // Own player information ).ToListAsync();

var item = items[0];

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); // User ID list to allow participation Debug.Log(item.Metadata); // metadata Debug.Log(item.ExpiresAt); // Gathering expiration date Debug.Log(item.CreatedAt); // Creation date and time Debug.Log(item.UpdatedAt); // Last updated date

var domain = gs2.Matchmaking.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession object (access token) ); var it = domain.DoMatchmaking(
new EzPlayer
{
RoleName = "attacker",
} // Own player information ); var items = new List<EzGathering>(); while (it.HasNext()) {
yield return it.Next();
if (it.Error != null)
{
onError.Invoke(it.Error, null);
break;
}
if (it.Current != null)
{
items.Add(it.Current);
}
else
{
break;
} } var item = items[0];

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); // User ID list to allow participation Debug.Log(item.Metadata); // metadata Debug.Log(item.ExpiresAt); // Gathering expiration date Debug.Log(item.CreatedAt); // Creation date and time Debug.Log(item.UpdatedAt); // Last updated date

Matchmaking Interruption

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

Matchmaking Cancel Implementation Example (Unity)

var domain = gs2.Matchmaking.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession object (access token) ).Gathering(
gatheringName: "gathering-0001" // gathering name ); var result = await domain.CancelMatchmakingAsync( ); 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); // User ID list to allow participation Debug.Log(item.Metadata); // metadata Debug.Log(item.ExpiresAt); // Gathering expiration date Debug.Log(item.CreatedAt); // Creation date and time Debug.Log(item.UpdatedAt); // Last updated date

var domain = gs2.Matchmaking.Namespace(
namespaceName: "namespace-0001" // namespace name ).Me(
gameSession: GameSession // GameSession object (access token) ).Gathering(
gatheringName: "gathering-0001" // gathering name ); var future = domain.CancelMatchmaking( ); yield return future; if (future.Error != null) {
onError.Invoke(future.Error, null);
yield break; } var future2 = future.Result.Model(); yield return future2; if (future2.Error != null) {
onError.Invoke(future2.Error, null);
yield break; } var result = future2.Result;

Debug.Log(result.GatheringId); // gathering GRN Debug.Log(result.Name); // gathering name Debug.Log(result.AttributeRanges); // Recruitment conditions Debug.Log(result.CapacityOfRoles); // participants Debug.Log(result.AllowUserIds); // User ID list to allow participation Debug.Log(result.Metadata); // metadata Debug.Log(result.ExpiresAt); // Gathering expiration date Debug.Log(result.CreatedAt); // creation date and time Debug.Log(result.UpdatedAt); // Last updated date

Rating

You can use the ratings provided by GS2-Matchmaking 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/lose results.
If the game server can determine the win or lose, the game server can report the win or lose.
GS2-Realtime will also be able to report win/lose results.
On the other hand, when the client reports the win/lose result, such as in P2P games, it is necessary to prevent cheaters from falsifying the win/lose result.
Therefore, GS2-Matchmaking provides a way for clients to vote for the winners.

Ballots and Voting

Clients who participate in a match will vote on a ballot and each player's win/lose and ranking.
GS2-Matchmaking determines the winner by majority vote and calculates the rating.
Although each client can vote separately to GS2-Matchmaking in this way, 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 the When the majority of the ballots have been collected, we recommend that the representative client notify each client of the result by sending a ballot to the GS2-Matchmaking system.
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/lose 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 lose, 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-MegaField

Service Overview

This service is designed to hold the location data of over 100,000 players and update it up to 5 times per second to share with other players.

A namespace can consist of multiple areas, with one area consisting of multiple layers.
For spaces where players do not clearly intersect, it is recommended to divide the area and separate layers for each type of player and drop items, etc.
If you want to place drop items or enemies in a space, you need to prepare a separate daemon to manage their status.

This service cannot share data other than X, Y, Z three-dimensional coordinates.
If you want to share other data, please consider combining other GS2 services.

This service is extremely communication-intensive.
Sending location information 3 times per second generates approximately 10,000 communications per hour, which costs more than USD 2.
Even if you are considering using the Individual plan, if the average number of requests per month exceeds 10 requests, you will be excluded from the plan and will not be able to use the service.
Please note that if you send your location 3 times per second, you will fall under the exclusion if you have an average of 3.3 people online.

Pricing

General usage

USD 0.0002 per API request

Service-specific

No service-specific usage fees

Restrictions and limitations

Each user can update coordinates up to 5 times per second

Basic usage

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

USD 0.0002 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.

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)

var domain = gs2.Mission.Namespace(
    namespaceName: "namespace-0001" // 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
);

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet issued
var domain = gs2.Mission.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Complete(
    missionGroupName: "mission-group-0001" // mission group name
);
var future = domain.ReceiveRewards(
    missionTaskName: "mission-task-0001" // task name
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet issued

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.

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

USD 0.0002 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 USD 100, 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 USD 2 and then acquire 100 in-game currency for USD 1, GS2-Money will not treat you as having 200 in-game currency with a unit price of USD 0.015 for cash, but will treat you as having 100 in-game currency with a unit price of USD 0.02 for cash and 100 in-game currency with a unit price of USD 0.01 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 USD 0.01, or 100 in-game currency with a cash unit price of USD 0.01 and USD 0.02, 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: "namespace-0001" // 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
var domain = gs2.Money.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Wallet(
    slot: 0 // slot number
);
var future = domain.Withdraw(
    count: 50, // quantity of billable currency to consume
    paidOnly: null // whether to target paid currency only
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;
var price = future.Result.Price;

Debug.Log(result.Slot); // slot number
Debug.Log(result.Paid); // Paid currency amount
Debug.Log(result.Free); // Amount of unpaid currency
Debug.Log(result.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 USD 100,000 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.
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 article data.
It parses YAML Front matter in index.* and extracts information such as publication period.
Therefore, the tree structure of article data must follow this /content/{sectionName}/{contentName} format.
Front Matter, which is described at the top of the content, must be described in YAML format.

GS2's own control syntax, described below, can be described in Front Matter.
If you define the conditions for publishing content in the Publish Period Setting, GS2-News will delete content that does not meet the conditions for publishing and build the site.
GS2-News will pre-build all patterns of public/private status of content with publication conditions set and place them on the web server.
Therefore, if there is a large number of content with publication conditions set, a combination explosion will occur, increasing the time and cost of updating the site.
To avoid this, try to minimize the number of contents with publication conditions set.

The "-D, --buildDrafts" option is not included in the build of article data.
Content described as draft: true in Front Matter will not be delivered.

Displaying Article Data

Two methods are provided for clients to display currently available article data in WebView or a browser.

Control syntax for Front Matter

Publish Period Setting

x_gs2_scheduleEventId: ${GS2-Schedule's event GRN}

By writing x_gs2_scheduleEventId, 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

USD 0.0002 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)

var domain = gs2.News.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).News(
);
List<EzSetCookieRequestEntry> cookies = new List<EzSetCookieRequestEntry>();
var result = await domain.GetContentsUrlAsync(
);
var items = result.ToList();
foreach (var item in items)
{
    var entry = await item.ModelAsync();
    cookies.Add(entry);
}

var browserUrl = domain.BrowserUrl;
var zipUrl = domain.ZipUrl;

Debug.Log(cookies); // list of cookies that need to be set to access the notification content
Debug.Log(browserUrl); // URL to access the announcement contents
Debug.Log(zipUrl); // URL to access ZIP contents of announcements Cookie setting is not necessary
var domain = gs2.News.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).News(
);
var future = domain.GetContentsUrl(
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;
List<EzSetCookieRequestEntry> cookies = new List<EzSetCookieRequestEntry>();
var items = result.ToList();
foreach (var item in items)
{
    var future2 = item.Model();
    yield return future2;
    var entry = future2.Result;
    cookies.Add(entry);
}
var browserUrl = domain.BrowserUrl;
var zipUrl = domain.ZipUrl;

Debug.Log(cookies); // list of cookies that need to be set to access the notification content
Debug.Log(browserUrl); // URL to access the announcement contents
Debug.Log(zipUrl); // URL to access ZIP contents of announcements Cookie setting is not necessary

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

USD 0.0002 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)

var domain = gs2.Quest.Namespace(
    namespaceName: "namespace-0001" // 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)
);

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet issued
var domain = gs2.Quest.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
);
var future = domain.Start(
    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 future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var result = future.Result;

Debug.Log(result.TransactionId); // Transaction ID of the stamp sheet issued

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)

var domain = gs2.Quest.Namespace(
    namespaceName: "namespace-0001" // 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 EzReward[] {
        {}
    }, // actual rewards from the quest (optional)
    config: null // optional configuration values to be applied to stamp sheet variables
);
var progress = await domain.ModelAsync();

Debug.Log(result.TransactionId); // transaction ID
Debug.Log(progress.ProgressId); // Quest progress GRN
Debug.Log(progress.TransactionId); // transaction ID
Debug.Log(progress.QuestModelId); // Quest model
Debug.Log(progress.RandomSeed); // random number seed
Debug.Log(progress.Rewards); // maximum reward from the quest
var domain = gs2.Quest.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Progress(
);
var future = domain.End(
    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 future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future.Result;
var progress = future2.Result;

Debug.Log(result.TransactionId); // transaction ID
Debug.Log(progress.ProgressId); // Quest progress GRN
Debug.Log(progress.TransactionId); // transaction ID
Debug.Log(progress.QuestModelId); // Quest model
Debug.Log(progress.RandomSeed); // random number seed
Debug.Log(progress.Rewards); // maximum reward from the quest

When you complete the quest, you can specify the reward you actually got from the quest.
If you do not specify, you will get all the rewards responded to at the start. If the reward is reduced due to ignoring enemies or treasure chests in the game, report the reduced quantity here.
Attempting to obtain more rewards than determined at the start or attempting to obtain rewards that cannot be obtained will result in an error.

There is a possibility of cheating by the client being able to call the completion of a quest, thereby reporting that the player has completed a stage of a difficulty that is not originally cleared 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 the quest completion report. The quest completion process is held until the stamp sheet is executed.

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

USD 0.0002 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)

var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace-0001" // 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
var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Ranking(
    categoryName: "category-0001" // category name
);
var future = domain.PutScore(
    score: 1000L, // score
    metadata: null // metadata (optional)
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var item = future2.Result;

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.

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)

var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
);
var items = await domain.RankingsAsync(
    categoryName: "category-0001" // category name
).ToListAsync();

Debug.Log(items); // list of rankings
var domain = gs2.Ranking.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
);
var it = domain.Rankings(
    categoryName: "category-0001" // category name
);
List<EzRanking> items = new List<EzRanking>();
while (it.HasNext())
{
    yield return it.Next();
    if (it.Error != null)
    {
        onError.Invoke(it.Error, null);
        break;
    }
    if (it.Current != null)
    {
        items.Add(it.Current);
    }
    else
    {
        break;
    }
}

Debug.Log(items); // list of rankings

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

USD 0.0002 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 USD 0.0004
realtime1.micro USD 0.0006
realtime1.small USD 0.0012
realtime1.medium USD 0.0024
realtime1.large USD 0.005

Data transfer capacity (outbound)

USD 0.015/1GB

--- (a)

If you cannot tolerate a cold start, a hot standby is available at USD 15 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

USD 0.0002 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

USD 0.0002 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 using GS2-Script.

Register the script on the "Script > Namespace List" page of the Management Console.
For example, looking at the GS2-Account namespace information, you can set up scripts to be executed at the time of account creation and authentication.

The script will be executed at the timing when the game player generates an event that is covered by the GS2 service.

Via GS2-JobQueue

Triggers whose execution timing is at/after completion of an event can be executed by specifying an arbitrary namespace for GS2-JobQueue and registering the script as a job in GS2-JobQueue.
The advantages of going through GS2-JobQueue include the ability to retry up to a certain number of times if a job fails to execute, the fact that jobs that fail more than a certain number of times are recorded as dead letter jobs, and the API's response speed is not easily slowed down.
Please check GS2-JobQueue for details on how to use GS2-JobQueue.

Confirmation of script execution results

Not only GS2-Script, but also other scripts and API calls can be checked by outputting logs to GS2-Log.
Please configure log output settings in the service's namespace settings.

Scripts are triggered when various events (API calls) are generated by the game player, but the return value of the API call does not include the result of the API call executed in the script.
If the client needs to present the results of the script execution to the game player, it can receive the results separately via GS2-JobQueue.

Script Sample

More billable currency (Lua)

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 trigger.
Sample script code can be found in the GS2-Script tab of the Methods section of the GS2 SDK Reference for each service.

GS2-SerialKey

Service Overview

This service is for handling serial codes or campaign codes.
Serial codes cannot be used once, while campaign codes are used on the premise that all players use the same code and that the code cannot be used more than once, for example, by using GS2-Limit's limit on the number of times it can be used.
Serial codes should be used by preparing a GS2-Exchange redemption rate that allows players to be compensated for the use of the serial code, for example.

Pricing

General usage

USD 0.0002 per API request

Service-specific

Serial code issuance USD 0.00005 per serial code

Restrictions and limitations

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

Basic usage

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

USD 0.0002 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)

var domain = gs2.Showcase.Namespace(
    namespaceName: "namespace-0001" // 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 = await result.ModelAsync();

Debug.Log(item.Name); // product name
Debug.Log(item.Metadata); // product metadata
var domain = gs2.Showcase.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Showcase(
    showcaseName: "showcase-0001" // product name
);
var future = domain.Buy(
    displayItemId: "display-item-0001", // display item ID
    quantity: null, // quantity of items purchased
    config: null // Optional configuration value to apply to stamp sheet variables
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result.Name); // product name
Debug.Log(result.Metadata); // product metadata

It is important to note that simply executing 'buy' itself does not result in the purchase of an item.
It is done by processing the stamp sheet that is the return value of 'buy'.

Also, 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

USD 0.0002 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.

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.

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)

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();

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
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 future = domain.Consume(
    consumeValue: 50 // amount of stamina to consume
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(future.Error, null);
    yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
    onError.Invoke(future2.Error, null);
    yield break;
}
var result = future2.Result;

Debug.Log(result.StaminaName); // name of stamina model
Debug.Log(result.Value); // Stamina value at last update
Debug.Log(result.MaxValue); // maximum value of stamina
Debug.Log(result.RecoverIntervalMinutes); // Stamina recovery interval (minutes)
Debug.Log(result.RecoverValue); // Stamina recovery amount
Debug.Log(result.NextRecoverAt); // Time for next time stamina is recovered

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

USD 0.0002 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 allows version checking to be performed
  3. Check version

Create master data

It is created from the Management Console.
The version to be set in the version master data will be the version that notifies the client that it is not the latest or similar version and is subject to being prompted for an update.
Therefore, the latest version will not be registered in the master.

The fact that the client's version did not match the version registered in the master is proof that the application is a version that does not interfere with game play.

Up to 10 version masters can be registered per namespace, and a game can be played if it can pass a maximum of 10 different version checks.

Example of a template that returns a project token for an elevated security policy upon passing a version check (YAML)

GS2TemplateFormatVersion: "2019-05-01"

Globals:
  Alias:
    VersionNamespaceName: application-0001
    ApplicationUserName: application
    ElevationUserName: authorized-application

Resources:
  IdentifierElevationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ElevationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierElevationUser

  IdentifierElevationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ElevationUserName}

  VersionNamespace:
    Type: GS2::Version::Namespace
    Properties:
      Name: ${VersionNamespaceName}
      AssumeUserId: !GetAttr IdentifierElevationUser.Item.UserId
    DependsOn:
      - IdentifierElevationUser

  VersionSettings:
    Type: GS2::Version::CurrentVersionMaster
    Properties:
      NamespaceName: ${VersionNamespaceName}
      Settings:
        version: 2019-10-09
        versionModels:
          - name: application
            metadata: application
            warningVersion: 
              major: 1
              minor: 0
              micro: 0
            errorVersion:
              major: 0
              minor: 9
              micro: 0
            scope: passive
            needSignature: false
    DependsOn:
      - VersionNamespace
Type of version value used for judgment

There are two version values to compare with the version value set in the master data.
The version value is specified in the scope of EzVersionModel.

Value Type of version value used for judgment Main applications
passive Compare with version value sent by client App, asset version, etc.
active Compare with versions that have been explicitly approved in the past Terms of use, security policy versions, etc.

Creating a security policy that only allows version checking to be performed

The basic usage envisioned is as follows

  1. the credentials used for version checking on the game application side should include
  2. grant only the necessary permissions (e.g., UnauthenticatedAccess security policy) to the credential to be used for version checking on the game application side; 2.
    When the game is launched, the version check is first performed using the credentials in 1.
    • If the version check passes, have the game retrieve enough project tokens to run the game
    • If the version check does not pass, direct the user to an app store or other source to update the application

You will need to create a credential with only the permissions necessary to perform the version check.

Example template for generating credentials with UnauthenticatedAccess security policy (YAML)

GS2TemplateFormatVersion: "2019-05-01"

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:UnauthenticatedAccess
    DependsOn:
      - IdentifierApplicationUser

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

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

Version check

Before the version check process, initialize GS2 with the above credentials and perform the login process.

Preparation of version information

First, prepare the client version information.

Example of preparing client version information (Unity)

List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.VersionName = "sample";

EzVersion version = new EzVersion();
version.Major = 1; //input actual client version Major version
version.Minor = 2; //input actual client version Minor version
version.Micro = 3; //input actual client version Micro version
targetVersion.Version = version;
targetVersions.Add(targetVersion);
List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.VersionName = "sample";

EzVersion version = new EzVersion();
version.Major = 1; //input actual client version Major version
version.Minor = 2; //input actual client version Minor version
version.Micro = 3; //input actual client version Micro version
targetVersion.Version = version;
targetVersions.Add(targetVersion);

version check

Next, the version checking API is executed with the version information as an argument.

Version check Implementation example (Unity/UniTask is enabled)

var domain = gs2.Version.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Checker();
var result = await domain.CheckVersionAsync(
    targetVersions: targetVersions.ToArray()
);

Debug.Log(result.ProjectToken); // project token
Debug.Log(result.Warnings); // list of warning version validation results
Debug.Log(result.Errors); // list of error version validation results
var domain = gs2.Version.Namespace(
    namespaceName: "namespace-0001" // namespace name
).Me(
    gameSession: GameSession // GameSession object (access token)
).Checker();
var future = domain.CheckVersion(
    targetVersions: targetVersions.ToArray()
);
yield return future;
if (future.Error != null)
{
    onError.Invoke(
        future.Error
    );
    yield break;
}
var result = future.Result;

Debug.Log(result.ProjectToken); // project token
Debug.Log(result.Warnings); // list of warning version validation results
Debug.Log(result.Errors); // list of error version validation results

The return values 'Warnings' and 'Errors' contain version information that could not be passed.
Warnings' and 'Errors' are lists.
If the size of each is 0, there is no problem with the version => start the game, if the size of either is 1 or more, there is no problem with the version => start the game.
If either size is 1 or more, there is a problem with the version => prompt for version upgrade.
If either size is greater than 1, there is a problem with the version => prompt for version upgrade.

Switching project tokens

The return value projectToken will be the project token of the user with the elevated security policy (e.g. ApplicationAccess security policy).
To switch API access to this project token, pass projectToken to the utility class Profile's UpdateProjectToken.
Subsequent API access will switch to the elevated privileges.

Project Token Switching Implementation Example (Unity)

// ProjectToken switching
Profile.UpdateProjectToken(projectToken);
// ProjectToken switching
Profile.UpdateProjectToken(projectToken);
signature verification

During the version check, a signature verification process can be added to prevent the declaring client from declaring an abusive false version value.
This is a countermeasure against cheaters who intentionally continue to play with an older version of the client application.

Pre-calculate the signature associated with the version value and set the signature on the EzVersion to be sent.
The signature is calculated by calculateSignature.

Example of calculating version signatures (C#)

var session = new Gs2RestSession(
    new BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    Region.ApNortheast1
);
yield return session.Open();
var client = new Gs2VersionRestClient(session);

AsyncResult<Gs2.Gs2Account.Result.CreateNamespaceResult> asyncResult = null;
yield return client.calculateSignature(
    new CalculateSignatureRequest()
        .withNamespaceName("namespace-0001")
        .withVersionName("sample")
        .withVersion({'major': 1, 'minor': 2, 'micro': 3}),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;

var body = result.Body;
var signature = result.Signature;

On the server side, enable the "needSignature" (requires signature verification) of the version model master data EzVersionModel.
In addition, it is recommended to consider embedding the signature information in the native code or encrypting the signature information when it is statically stored on the client side.

Example of setting signature information (bodyAsignature) in version information (Unity)

List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.VersionName = "sample";

EzVersion version = new EzVersion();
version.Major = 1;
version.Minor = 2;
version.Micro = 3;
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.Version = version;
targetVersion.VersionName = "sample";

targetVersion.Body = body;
targetVersion.Signature = signature;

targetVersions.Add(targetVersion);
List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.VersionName = "sample";

EzVersion version = new EzVersion();
version.Major = 1;
version.Minor = 2;
version.Micro = 3;
EzTargetVersion targetVersion = new EzTargetVersion();
targetVersion.Version = version;
targetVersion.VersionName = "sample";

targetVersion.Body = body;
targetVersion.Signature = signature;

targetVersions.Add(targetVersion);

Stamp Sheet

What is a stamp sheet?

Stamp sheet concept

GS2 has a system called Stamp Sheet that links all services together.
This system makes it possible to implement processes that are conditional on the execution of resource operations and other operations performed by other services.

The StampSheet is a system similar to a request for approval in a company.
When each service gives its approval, it puts its stamp (signature) on the sheet, and the process can be executed when everything is in order.

The process such as consumption of resources required for approval is called a stamp task.
If the requested Stamp Task can be executed for each service, a Stamp is obtained.
When all the stamps are stamped on the stamp sheet, the processing of that stamp sheet and each stamp task can be executed.

For example, if you are processing a reward for completing a quest, you can set the reduced stamina value or reduced number of orders allowed in the stamp task and and Get Experience and Rewrite Quest Clear Flag as rewards for the consumption. 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 service in GS2.

The StampTask is a task to fulfill the conditions necessary to execute the API of the target service of the StampSheet, and Actions (consumeActions) can be set to reduce user resources.

The StampSheet can have actions that increase the user's resources on completion (completeAcquireActions), actions that actions that 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) (Unity)

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,
        },
    }
);
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",
  "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
config AcquireActionConfig[] [] List of Acquisition config

Gs2Formation:AcquireActionsToPropertyFormProperties

Add resources to properties to be organized using stamp sheets

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "formModelName": "[string]Mold Name",
  "propertyId": "[string]Property Id",
  "acquireAction": "[AcquireAction]Get action to be applied to form properties",
  "config": "[AcquireActionConfig[]]List of Acquisition config"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
formModelName string ~ 128 chars Mold Name
propertyId string ~ 1024 chars Property Id
acquireAction AcquireAction Get action to be applied to form properties
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]Datetime of ttl",
  "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 Datetime of ttl
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}"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id

Gs2Exchange:DeleteAwaitByUserId

Delete Waiting for Exchange in Stamp Task

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "awaitName": "[string]Exchange standby name"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
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

Gs2SerialKey:UseByUserId

Use Stamp Tasks to Consume Serial Code

{
  "namespaceName": "[string]Namespace name",
  "userId": "#{userId}",
  "code": "[string]Serial Code"
}
Type Require Default Limitation Description
namespaceName string ~ 32 chars Namespace name
userId string ~ 128 chars User Id
code string ~ 48 chars Serial Code

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 (JSON)
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 1 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.)

Errors/Exceptions

Composition of error messages

Example: [{"component": "progress", "message": "quest.progress.progress.error.notFound"}]

Section Description
"component": Indicates the target where the error occurred and contains the member name and method name.
"message": Details of the error location and keywords indicating the error.
service name. component.error.error content.
Major error content description
failed Processing failed.
invalid Illegal parameter.
require Missing required argument.
tooLong Argument is too long.
exists The parameter already exists.
duplicate Duplicate, already exists.
notFound Not found.
notAuthorized Could not authorize.
notMatch No match was found.
deny rejected
banned Banned.

Type of Exception

When an error occurs in GS2, the following exceptions occur.

exception error content status code
BadRequestException The request content is invalid. 400
UnauthorizedException The authorization required to connect to GS2 could not be authenticated; also occurs when the access token used for API access has expired. 401
QuotaLimitExceededException Quota (allocation) limit exceeded. 402
NotFoundException The object of the request could not be found. 404
ConflictException Conflict occurred. 409
InternalServerErrorException An error occurred on the server. 500
BadGatewayException The server received an invalid response. 502
ServiceUnavailableException An error occurred in the service. 503
RequestTimeoutException Request timed out. 504
UnknownException Unknown exception occurred.

Functions-Services Index

User Data Management

Function Service Name
Account Management GS2-Account GS2-Auth
Experience and Rank GS2-Experience
Equipment GS2-Formation
Possessions GS2-Inventory
Inventory GS2-Inventory
Gold In-Game Currency Management GS2-Inventory
Billing Currency GS2-Money
Stamina GS2-Stamina
Pictorial book GS2-Dictionary

Game cycle

Function Service Name
Item Enhancement and Synthesis GS2-Enhance
Resource Exchange GS2-Exchange
Gift Boxes GS2-Inbox
Lottery GS2-Lottery
Mission GS2-Mission
Quests GS2-Quest
In-game store GS2-Showcase

Communication

Function Service Name
Chat GS2-Chat
Binary Data Storage GS2-Datastore
Party Formation GS2-Formation
Friend GS2-Friend
Matchmaking Function GS2-Matchmaking
Ranking GS2-Ranking
Matchmaking/Cooperative play functionality GS2-Realtime

Operation

Function Service Name
Gift Boxes GS2-Inbox
Notices GS2-News
Event Schedule Management GS2-Schedule
Version Management GS2-Version

System

Function Service Name
Save when number of possession is exceeded GS2-Distributor
Push notification (in-game) GS2-Gateway
Asynchronous job execution GS2-JobQueue
Encryption key management GS2-Key
Limit GS2-Limit
Exclusion handling GS2-Lock

Management

Function Service Name
Resource building GS2-Deploy
Authentication and authority management GS2-Identifier
Log output GS2-Log

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