# PC SDK Unity Integration Guide

# Introduction

The STOVE platform for games provides integrated services. All processes of game release, including game distribution and sales, community, and indicator analysis, can be handled in one-stop. With the PC SDK (Unity, hereafter referred to as PC SDK), you can easily integrate the services provided by the Stove platform into your game.

This section describes how to integrate the PC SDK.

confirmIf this is the first time you are trying to integrate PC SDK, please read the PC SDK Unity Follow Through Through first.

# Preparations

  • Check that you have issued the stove subscription account and the App key, App secret, and Game Id for the released game from STOVE Studio (opens new window).
  • We recommend installing versions of Unity 2017 and Visual Studio 2017 or higher.
  • Download the newest Unity(C#) distributed files(stated as StovePCSDK_NET from here on) from the PC SDK Download page.

# StovePCSDK_NET Distributed File Configuration

# 1) StovePCSDK Folder

The folders below can be found in the StovePCSDK folder when you download and unzip StovePCSDK_NET.

  • Plugins Unity Project plugin folder.

  • Plugins\x86
    Binaries required for x86 builds.

  • Plugins\x86_64
    Binaries required for x64 builds.

# Configuring StovePCSDK_NET Build Settings

# 1) Adding Assets

Open the Unity project to be integrated. Leave one of the x86/x86_64 folders in the ‘StovePCSDK folder described above and delete the other one. Then copy the StovePCSDK folder and paste it under the Assets folder.

Figure1
Figure2

# 2) Checking Files in the x86 Folder

Select the files in the x86 folder and check if you have selected the Windows x86 category in the inspector's platform settings section. Select it if you don't choose it.

Figure3
Figure4

# 3) Checking Files in the x86_64 Folder

Select the files in the x86 folder and check if you have selected the Windows x86_x64 category in the inspector's platform settings section. Select it if you don't choose it.

Figure5
Figure6

# 4) Build Settings

Click the File > Build Settings... menu to open the Build Settings dialog and click the Player Settings... button to open the Inspector or Project Settings window. Set Other Settings group > Configuration section > Api Compatibility Level item as below.

Unity 2018 and earlier versions: .NET 2.0 (not .NET 2.0 Subset)

Figure11

Unity 2018 and higher: .NET 4.x (not .NET Standard 2.0)

Figure12

# 5) Creating an Empty Game Object

Create a GameObject (GameObject -> Create Empty) in the appropriate scene. Set the name of the empty GameObject to StovePCSDKManager for convenience.

Figure7
Figure8

# 6) Adding Script Components

Add a script component to the StovePCSDKManager object.
Set the script’s name as StovePCSDKManager for convenience.

Figure9
Figure10

# 7) Script Input

Process the Awake method as shown below so that it doesn't disable the StovePCSDKManager object due to scene changes or such.

private void Awake()
{
    DontDestroyOnLoad(transform.gameObject);
}
1
2
3
4

# Integration

# 1) RunCallback

It processes PC SDK’s API mostly unsynchronized not to disturb the game engine and game logic.
It loads the result of the API call on the PC SDK’s internal queue. It executes the registered callback when the game calls the RunCallback method to process the result of the API call. Usually, the RunCallback method’s call is input through a coroutine, and you can set the call cycle.

private IEnumerator RunCallback(float intervalSeconds)
{
    WaitForSeconds wfs = new WaitForSeconds(intervalSeconds);
    while (true)
    {
        StovePC.RunCallback();
        yield return wfs;
    }
}
1
2
3
4
5
6
7
8
9

A coroutine is started via the MonoBehaviour.StartCoroutine method and is usually a PC SDK initialization. It starts with success and stops if PC SDK shutdown succeeds. There is a way to use a member variable to stop the RunCallback coroutine after the successful PC SDK shutdown.

private Coroutine runcallbackCoroutine;
1

You can operate the runcallbackCoroutine declared as a member variable in the game project like a timer by using the StartCoroutine and StopCoroutine functions as shown in the code below.

public void ToggleRunCallback_ValueChanged(bool isOn)
    {
        if (isOn)
        {
            float intervalSeconds = 1f;
            runcallbackCoroutine = StartCoroutine(RunCallback(intervalSeconds));

            WriteLog("RunCallback Start");
        }
        else
        {
            if (runcallbackCoroutine != null)
            {
                StopCoroutine(runcallbackCoroutine);
                runcallbackCoroutine = null;

                WriteLog("RunCallback Stop");
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2) Config, Callback Settings

To initialize PC SDK, start with filling in the values for the StovePCConfig and StovePCCallback structures and call the StovePC.Initialize method.
Refer to the code below to fill in each field value within the StovePCConfig structure.

StovePCConfig config = new StovePCConfig
{
    Env = "live",
    AppKey = "YOUR_APP_KEY",
    AppSecret = "YOUR_SECRET_KEY",
    GameId = "YOUR_GAME_ID",
    LogLevel = StovePCLogLevel.Dubug,
    LogPath = ""
};
1
2
3
4
5
6
7
8
9

confirm
You must change "YOUR_APP_KEY", "YOUR_SECRET_KEY", and "YOUR_GAME_ID" to data with the key-value issued by STOVE Studio. If you call the StovePC.Initialize method without logging in to the stove launcher, an error occurs. Run the stove launcher before logging in.

Interworking between the game and the PC SDK uses a C# delegate. You must define delegate methods connected to the callbacks of the StovePCCallback class below for games.

public class StovePCCallback
{
    // Callback called when errors occur in StovePCSDK 
    public StovePCErrorDelegate OnError; 
    
    // Callback called when the PC SDK initialization is complete 
    public StovePCInitializationCompleteDelegate OnInitializationComplete; 
    
    // Callback called when the GetToken process is complete 
    public StovePCTokenDelegate OnToken; 
    
    // Callback called when the GetUser process is complete 
    public StovePCUserDelegate OnUser; 
    
    // Callback called when the GetOwnership process is complete 
    public StovePCOwnershipDelegate OnOwnership;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Be careful so that the StovePCCallback object is maintained until it terminates PC SDK. The PC SDK cannot internally call a callback if you collect the StovePCCallback object as garbage.
To satisfy this condition, you can define the StovePCCallback class as a member variable. To satisfy this point, you can solve this by declaring the StovePCCallback class as a member variable of the game project class to prevent garbage collection.

private StovePCCallback callback;
1
// StovePCCallback class instance created
this.callback = new StovePCCallback
{
    OnError = new StovePCErrorDelegate(this.OnError),
    OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
    OnToken = new StovePCTokenDelegate(this.OnToken),
    OnUser = new StovePCUserDelegate(this.OnUser),
    OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership)
};
1
2
3
4
5
6
7
8
9

The OnError, OnInitializationComplete and OnOwnership callback functions must work together. You can integrate the rest of the callback functions only when necessary. For example, suppose you only use the Ownership function. In that case, you can implement it by defining it in the game project, as shown below.


/*
As for when only using the Ownership function,
apart from the essential callbacks OnError, OnInitializationComplete,
connect only the OnOwnership callback additionally.
*/
this.callback = new StovePCCallback
{
    OnError = new StovePCErrorDelegate(this.OnError),
    OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
    OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership)
};
1
2
3
4
5
6
7
8
9
10
11
12

# 3) SDK Initialization

Call the StovePC.Initialize method to initialize PC SDK.

StovePCResult sdkResult = StovePC.Initialize(config, this.callback);
if (StovePCResult.NoError == sdkResult)
{
    this.runCallbackCoroutine = StartCoroutine(RunCallback(0.5f);
    // Call RunCallback periodically due to no initialization errors
}
else
{
    // Quit the game due to initialization failure
}
1
2
3
4
5
6
7
8
9
10

After the StovePC.Initialize method checks only the config and callback validity, it immediately returns the type value of the StovePCResult enum.
In case of success, it returns a value of StovePCResult.NoError. In case of failure, it returns the corresponding error code, and you need to quit the game.

If the returned value is StovePCResult.NoError, therefore, a 'success', regularly call the StovePC.RunCallback method.
StovePC.RunCallback function must be regularly called to call the connected callback usually. The callback response speed slows down if the call cycle is long, so it is better to maintain an appropriate call cycle. In the example code, we set the callback function to be called once per second.

confirm The thread that initializes the PC SDK with the Initialize method and the thread on which it calls the callback function with the StovePC.RunCallback method must be the same.

The StovePC.Initialize function processes unsynchronized procedures, excluding the config and callback validity check.
It calls the OnInitializationComplete callback if the unsynchronized procedures are successful. It calls the OnError callback if an error occurs.
You can check the error code and message through the delivered StovePCError structure in case of an error.

private void OnInitializationComplete()
{
    Debug.Log("PC SDK initialization success");
}

    private void OnError(StovePCError error)
    {
        #region Log
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("OnError");
        sb.AppendFormat(" - error.FunctionType : {0}" + Environment.NewLine, error.FunctionType.ToString());
        sb.AppendFormat(" - error.Result : {0}" + Environment.NewLine, (int)error.Result);
        sb.AppendFormat(" - error.Message : {0}" + Environment.NewLine, error.Message);
        sb.AppendFormat(" - error.ExternalError : {0}", error.ExternalError.ToString());
        WriteLog(sb.ToString());
        #endregion

        switch (error.FunctionType)
        {
            case StovePCFunctionType.Initialize:
            case StovePCFunctionType.GetUser:
            case StovePCFunctionType.GetOwnership:
                BeginQuitAppDueToError();
                break;
        }
    }

private void BeginQuitAppDueToError()
    {
        #region Log
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("BeginQuitAppDueToError");
        sb.AppendFormat(" - nothing");
        WriteLog(sb.ToString());
        #endregion

        // After showing the user a message about app outage rather than stopping it immediately
        // Depending on user action (e.g. clicking the exit button), you may want to terminate the app.
        // If so, erase QuitApplication here and implement your own logic.
        // Recommended messages for required pre-task errors are as follows.
        // Korean: The required pre-task failed to operate and the game has been terminated.
        // Other Languages: The required pre-task fails and exits the game.
        QuitApplication();
    }    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

You can use the StovePC.GetInitializationState method if there is a need to check the initialized status value of PC SDK before the OnInitializationComplete callback is received.

//After calling the StovePC.Initialize
while (StovePC.GetInitializationState() == StovePCInitializationState.Pending)
{
    Thread.Sleep(500);
    StovePC.RunCallback();
}

if (StovePC.GetInitializationState() == StovePCInitializationState.Complete)
{
    // The OnInitializationComplete callback is called when initialization is complete
}
else
{
    // OnError callback is called when initialization has failed
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 4) Cautions when integrating the SDK

confirm If the GetToken, GetUser, GetOwnership methods are called before initialization is complete, it may not return normal results. In other words, you must call the GetToken, GetUser, GetOwnership methods after receiving the callback of OnInitializationComplete to receive normal results.

confirm When setting the log level of the FStovePCConfig structure, enter the value StovePCLogLevel.Debug for the Debug build. For the official build, please set StovePCLogLevel.Error to prevent unnecessary log creation.

# 5) SDK Termination

Call after you've finished using the PC SDK to clean up resources in use. After you call the StovePC.Uninitialize method, the API of the PC SDK does not work. Before or after reaching the StovePC.Uninitialize method, you must stop the runcallbackCoroutine execution with the StopCoroutine function.

StovePCResult result = StovePC.Uninitialize();
if (result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5

# 6) Acquiring User Information

Use the StovePC.GetUser function to retrieve the logged-in user information in STOVE Launcher.

StovePCResult result = StovePC.GetUser();
if (result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5

The OnUser callback is called when the StovePC.GetUser function is processed properly.
You can know the user's memberNo, Nickname, Game User ID information through the StovePCUser structure passed to the callback.

private void OnUser(StovePCUser user)
{
    // Display user information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnUser");    
    sb.AppendFormat(" - user.MemberNo : {0}" + Environment.NewLine, user.MemberNo.ToString());
    sb.AppendFormat(" - user.Nickname : {0}" + Environment.NewLine, user.Nickname);
    sb.AppendFormat(" - user.GameUserId : {0}", user.GameUserId);

    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11

# 7) Acquiring Token Information

Get token information of the user who logged in to STOVE launcher with StovePC.GetToken method.

StovePCResult result = StovePC.GetToken();
if (result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5

The OnToken callback is called when the StovePC.GetToken function is processed properly.
It contains the token string in the StovePCToken structure delivered to the callback.

private void OnToken(StovePCToken token)
{
    // Display token information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnToken");
    sb.AppendFormat(" - token.AccessToken : {0}", token.AccessToken);

    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9

confirm What is a token? It is the access token of the logged-in user in STOVE Launcher, and the game server passes this access token to the stove authentication server to validate the logged-in user.
For a detailed explanation of Access Token, please get in touch with store.support@smilegate.com for technical support.

# 8) Acquiring Ownership Information

Use the StovePC.GetOwnership method to check if the user owns the game through purchase.

StovePCResult result = StovePC.GetOwnership();
if (result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5

The OnOwnership callback is called when the StovePC.GetOwnership function is processed properly.
Below is an example code that determines the purchase status of a game in the OnOwnership callback. If the game is without DLC, the confirmation code for lines 22 to 27 is unnecessary.

private void OnOwnership(StovePCOwnership[] ownerships)
{
    bool owned = false;
 
    foreach(var ownership in ownerships)
    {

        // [LOGIN_USER_MEMBER_NO] StovePCUser structure’s MemberNo 
        // [OwnershipCode] 1: Having the ownership, 2: Ownership removed (Cancelling the purchase)        
        if (ownership.MemberNo != LOGIN_USER_MEMBER_NO ||
            ownership.OwnershipCode != 1)
        {
            continue;
        }

        // [GameCode] 3: Package game, 4: DEMO
        if (ownership.GameId == "YOUR_GAME_ID" &&
            ownership.GameCode == 3)
        {
            owned = true; // Set ownership verification variable to true
        }

        // Required only for games selling DLC
        if (ownership.GameId == "YOUR_DLC_ID" &&
            ownership.GameCode == 5)
        {
            //User owns YOUR_DLC_ID(DLC). allow DLC play
        }
    }

     if(owned)
    {
        // Write game entry logic after ownership verification is usually completed
    }
    else
    {
        // After ownership verification fails, end the game and write an error message display logic
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  • You can play the game after logging in to the STOVE launcher with the account that purchased the game (with ownership).
  • After logging in to the STOVE launcher with an account that does not own the game, the following guide message (example) is output when you execute the exe and then terminate the game.
    • "Please log in to STOVE Client with the account that has purchased the game."

confirm You don't need an account with game ownership to test the ownership feature. See FAQ.

  • Please add the log about the result of the ownership call after <GetOwnership Success>. (output_log.txt or Player.log)
For example :

Success: The user has ownership.
Failure: The user has no ownership
1
2
3
4

# 9) Set language 2.6.0

Set the language with StovePC.SetLanguage function.
When initializing the PC SDK, the language is set as default using the system language (operating system language).
To explicitly set the system language (operating system language), enter system as a parameter.
To set a specific language, call the StovePC.SetLanguage function after successful initialization (e.g. OnInitializationComplete).

StovePCResult result = StovePC.SetLanguage("LANGUAGE_CODE");
if (result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

# 10) Language translation 2.6.0

Translate languages with StovePC.TranslateLanguage function.
PC SDK provides a translation for a specific string based on the set language information.
A specific string is managed as a String ID managed by the PC SDK.
If the game directly implements the PC SDK popup UI, the string displayed in the UI must display the translated string through the StovePC.TranslateLanguage function.

string translated = StovePC.TranslateLanguage("STRING_ID");
1

Precautions

Returns an English translation if there is no translation of a specific string for the language set in the PC SDK.
For exceptions or unsupported string IDs, the input parameter (string ID) is returned as it is.

# Checking Errors

The errors that occur while using the PC SDK are usually one of two cases.

# StovePCResult Enum Values Returned After Method Calls

All PC SDK's functions will return a StovePCResult enum value immediately after calling to mark whether the call was successful.
The entire value can be checked in the PC SDK Error Code page.

# StovePCError Structure Delivered Through OnError callbacks

Suppose an error occurs in an asynchronous function during the PC SDK function. In that case, it calls a OnError callback and delivers a StovePCError structure with a description of the error.

// Delivered when the OnError callback is called.
public struct StovePCError
{
    // Enum value showing the called function
    public StovePCFunctionType FunctionType;

    // Enum value showing the error type
    public StovePCResult Result;

    // Error message
    public string Message;

    // Error codes for external errors(http error, external module error)
    public int ExternalError;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Integrate Game support service

PC SDK provides API to integrate the Stove platform’s game support service into the game. The game support service supported by the PC SDK includes stats, achievements, and leaderboards. Each service is defined as follows:

  • Stats: A service that records the user’s various gameplay data in numerical terms
  • Achievements: A service that sets gameplay challenges and provides user-specific achievement information
  • Leaderboard: A service that provides user ranking information of specific gameplay data

To use the API for PC SDK game support service, you need to first conduct metadata registration for game support services through the studio.
For information on metadata management, refer to the Simple Console User Manual.

# 1) Callback Settings

To communicate with the PC SDK using the game support service API, you must define a class callback delegation method in the game to connect to the callback of the StovePCCallback class below.

public class StovePCCallback
{
    public StovePCErrorDelegate OnError;
    public StovePCInitializationCompleteDelegate OnInitializationComplete;
    public StovePCTokenDelegate OnToken;
    public StovePCUserDelegate OnUser;
    public StovePCOwnershipDelegate OnOwnership;
 
    // It calls the callback when you have completed GetStat.
    public StovePCStatDelegate OnStat;
 
    // It calls the callback when you have completed SetStat.
    public StovePCSetStatDelegate OnSetStat;
 
    // It calls the callback when you have completed GetAchievement.
    public StovePCAchievementDelegate OnAchievement;
 
    // It calls the callback when you have completed GetAllAchievement. 
    public StovePCAllAchievementDelegate OnAllAchievement;
 
        // It calls the callback when you have completed GetRank.
    public StovePCRankDelegate OnRank;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Connect the callback delegation to the callback of the StovePCCallback class as in Integration 2) Config, Callback Settings.

// Create instance of the StovePCCallback class
this.callback = new StovePCCallback
{
    OnError = new StovePCErrorDelegate(this.OnError),
    OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
    OnToken = new StovePCTokenDelegate(this.OnToken),
    OnUser = new StovePCUserDelegate(this.OnUser),
    OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership),
 
    // Game support service
    OnStat = new StovePCStatDelegate(this.OnStat),
    OnSetStat = new StovePCSetStatDelegate(this.OnSetStat),
    OnAchievement = new StovePCAchievementDelegate(this.OnAchievement),
    OnAllAchievement = new StovePCAllAchievementDelegate(this.OnAllAchievement),
    OnRank = new StovePCRankDelegate(this.OnRank)
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

You do not need to implement callbacks other than OnStat, OnSetStat, OnAchievement, OnAllAchievement, and OnRank.
You only need to implement and connect the callback methods required for the game support service used by the game.

# 2) Update User Stats

Update specific stats in the game for a logged-in user with the StovePC.SetStat method.

// Input parameters
// string statId : Stat identifier registered in the studio
// int statValue : Stat value to be updated
StovePCResult result = StovePC.SetStat("STAT_ID", STAT_VALUE);
if(result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5
6
7
8

When the StovePC.SetStat function is processed properly, the OnSetStat callback is called.
The StovePCStatValue structure delivered to the callback contains a flag indicating the current stat value, update status, and error messages.

Suppose it fully reflects and updates the stat value. In that case, the Updated field will contain ‘true’, and the ErrorMessage field will have an empty string. If the stat value is partially updated, the Updated field will contain ‘true’. The ErrorMessage field will contain a string such as “integer overflow”.

For example, you are assuming that the current stat value of the INCREMENT type is 2,147,483,000. You try to add 1,000 through the StovePC.SetStat API. It will become out of range of the values that the Int32 type can have. When it updates to 2,147,483,647, the maximum value of the Int32 type, reflecting only part of the value (1,000), the ErrorMessage field will contain a string such as “integer overflow”.

The table below lists the results that can obtain through the StovePCStatValue structure.

Stat Type Updated ErrorMessage Result
All Types True “”(Empty string) Requested value is fully updated to current value
INCREMENT True "integer overflow" Storage space exceeded, partial update
INCREMENT False "integer overflow" Storage space exceeded, no update
MIN False “”(Empty string) Requested value larger than current value
MAX False “”(Empty string) Requested value smaller than current value
REPLACE False “”(Empty string) Requested value same as current value
private void OnSetStat(StovePCStatValue statValue)
{
    // Display stat update result information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnSetStat");
    sb.AppendFormat(" - statValue.CurrentValue : {0}" + Environment.NewLine, statValue.CurrentValue.ToString());
    sb.AppendFormat(" - statValue.Updated : {0}" + Environment.NewLine, statValue.Updated.ToString());
    sb.AppendFormat(" - statValue.ErrorMessage : {0}", statValue.ErrorMessage);
   
    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11

confirm Caution) The valid range of the callback parameter StovePCStatValue structure is limited to the scope of the callback function. The PC SDK releases internally allocated memory as soon as execution of the callback function is completed. Therefore, if storage is required to use information of the StovePCStatValue structure outside of the scope of the callback function, a copy must be created through Deep Copy, and the memory must be released when use of the copy is completed.

When the StovePC.SetStat method is running, if an error occurs, the OnError callback is called.
You can check for external errors through the ExternalError field of the StovePCError structure.

ExternalError Description
2000 Invalid Access
3000 Wrong API Usage
4000 Stats ID Not Found
9000 Service Error

# 3) Get User Stat Information

Use the StovePC.GetStat function to retrieve specific game stat information for a logged-in user.

// Input parameters
// string statId : Stat identifier registered in the studio
StovePCResult result = StovePC.GetStat("STAT_ID");
if(result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5
6
7

When the StovePC.GetStat method is processed correctly, it calls the OnStat callback.
The StovePCStat structure delivered to the callback contains the current stat value.

private void OnStat(StovePCStat stat)
{
    // Display stat info
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnStat");
    sb.AppendFormat(" - stat.StatFullId.GameId : {0}" + Environment.NewLine, stat.StatFullId.GameId);
    sb.AppendFormat(" - stat.StatFullId.StatId : {0}" + Environment.NewLine, stat.StatFullId.StatId);
    sb.AppendFormat(" - stat.MemberNo : {0}" + Environment.NewLine, stat.MemberNo.ToString());
    sb.AppendFormat(" - stat.CurrentValue : {0}" + Environment.NewLine, stat.CurrentValue.ToString());
    sb.AppendFormat(" - stat.UpdatedAt : {0}", stat.UpdatedAt.ToString());
 
    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13

If an error occurs while the StovePC.GetStat method is running, if an error occurs, the OnError callback is called.
You can check for external errors through the ExternalError field of the StovePCError structure.

ExternalError Description
2000 Invalid Access
3000 Wrong API Usage
4000 Stats ID Not Found
9000 Service Error

# 4) Get User Single Achievement Information

Use the StovePC.GetAchievement method to retrieve specific game single achievement information for a logged-in user.

// Input parameters
// string achievementId : Achievement identifier created in the studio
StovePCResult result = StovePC.GetAchievement("ACHIEVEMENT_ID");
if(result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5
6
7

When the StovePC.GetAchievement method is processed correctly, it calls the OnAchievement callback.
The StovePCAchievement structure delivered to the callback contains the current achievement value, status, and achievement metadata.

private void OnAchievement(StovePCAchievement achievement)
{
    // Display single achievement information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnAchievement");
    sb.AppendFormat(" - achievement.AchievementId : {0}" + Environment.NewLine, achievement.AchievementId);
    sb.AppendFormat(" - achievement.Name : {0}" + Environment.NewLine, achievement.Name);
    sb.AppendFormat(" - achievement.Description : {0}" + Environment.NewLine, achievement.Description);
    sb.AppendFormat(" - achievement.DefaultImage : {0}" + Environment.NewLine, achievement.DefaultImage);
    sb.AppendFormat(" - achievement.AchievedImage : {0}" + Environment.NewLine, achievement.AchievedImage);
    sb.AppendFormat(" - achievement.Condition.GoalValue : {0}" + Environment.NewLine, achievement.Condition.GoalValue.ToString());
    sb.AppendFormat(" - achievement.Condition.ValueOperation : {0}" + Environment.NewLine, achievement.Condition.ValueOperation);
    sb.AppendFormat(" - achievement.Condition.Type : {0}" + Environment.NewLine, achievement.Condition.Type);
    sb.AppendFormat(" - achievement.Value : {0}" + Environment.NewLine, achievement.Value.ToString());
    sb.AppendFormat(" - achievement.Status : {0}", achievement.Status);
 
    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

If an error occurs while the StovePC.GetAchievement method is running, if an error occurs, the OnError callback is called.
You can check for external errors through the ExternalError field of the StovePCError structure.

ExternalError Description
1200 Not found achievement
9000 Service error

# 5) Get All User Achievement Information

Use the StovePC.GetAllAchievement method to retrieve specific game single achievement information for a logged-in user.

StovePCResult result = StovePC.GetAllAchievement();
if(result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5

When the StovePC.GetAllAchievement method is processed correctly, it calls the OnAllAchievement callback.
The StovePCAchievement structure delivered to the callback contains the current achievement value, status, and achievement metadata.

private void OnAchievement(StovePCAchievement[] achievements)
{
    // Display all achievement information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnAllAchievement");
    sb.AppendFormat(" - achievements.Length : {0}" + Environment.NewLine, achievements.Length);
 
    for (int i = 0; i < achievements.Length; i++)
    {
        sb.AppendFormat(" - achievements[{0}].AchievementId : {1}" + Environment.NewLine, i, achievements[i].AchievementId);
        sb.AppendFormat(" - achievements[{0}].Name : {1}" + Environment.NewLine, i, achievements[i].Name);
        sb.AppendFormat(" - achievements[{0}].Description : {1}" + Environment.NewLine, i, achievements[i].Description);
        sb.AppendFormat(" - achievements[{0}].DefaultImage : {1}" + Environment.NewLine, i, achievements[i].DefaultImage);
        sb.AppendFormat(" - achievements[{0}].AchievedImage : {1}" + Environment.NewLine, i, achievements[i].AchievedImage);
        sb.AppendFormat(" - achievements[{0}].Condition.GoalValue : {1}" + Environment.NewLine, i, achievements[i].Condition.GoalValue.ToString());
        sb.AppendFormat(" - achievements[{0}].Condition.ValueOperation : {1}" + Environment.NewLine, i, achievements[i].Condition.ValueOperation);
        sb.AppendFormat(" - achievements[{0}].Condition.Type : {1}" + Environment.NewLine, i, achievements[i].Condition.Type);
        sb.AppendFormat(" - achievements[{0}].Value : {1}" + Environment.NewLine, i, achievements[i].Value.ToString());
        sb.AppendFormat(" - achievements[{0}].Status : {1}", i, achievements[i].Status);
 
        if (i < achievements.Length - 1)
            sb.AppendFormat(Environment.NewLine);
    }

    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

If an error occurs while the StovePC.GetAchievement method is running, the OnError callback is called.
You can check for external errors through the ExternalError field of the StovePCError structure.

ExternalError Description
9000 Service error

# 6) Get Leaderboard Ranking Information

Use the StovePC.GetRank method to retrieve the ranking information of a specific game leaderboard.

// Input parameters
// string leaderboardId : Leaderboard identifier created in the studio
// uint pageIndex : Page number to search (1 <= pageIndex)
// uint pageSize : Number of ranks to search (1 <= pageSize <= 50)
// bool includeMyRank : Include rank of logged-in users in search results
StovePCResult result = StovePC.GetRank("LEADERBOARD_ID", PAGE_INDEX, PAGE_SIZE, INCLUDE_MY_RANK);
if(result == StovePCResult.NoError)
{
    // Processed as a success
}
1
2
3
4
5
6
7
8
9
10

confirm When requested with INCLUDE_MY_RANK:true, the first data in the response data list will return the ranking information of the logged-in user, and it returns subsequent page rank data.

When the StovePC.GetRank method is processed correctly, it calls the OnRank callback.
The StovePCRank structure delivered to the callback contains score and rank information for a specific user.

// Callback parameters
// uint rankTotalCount : Total number of rankings aggregated in the searched leaderboard
private void OnRank(StovePCRank[] ranks, uint rankTotalCount)
{
    // Display Ranking Information
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("OnRank");
    sb.AppendFormat(" - ranks.Length : {0}" + Environment.NewLine, ranks.Length);
 
    for (int i = 0; i < ranks.Length; i++)
    {
        sb.AppendFormat(" - ranks[{0}].MemberNo : {1}" + Environment.NewLine, i, ranks[i].MemberNo.ToString());
        sb.AppendFormat(" - ranks[{0}].Score : {1}" + Environment.NewLine, i, ranks[i].Score.ToString());
        sb.AppendFormat(" - ranks[{0}].Rank : {1}" + Environment.NewLine, i, ranks[i].Rank.ToString());
        sb.AppendFormat(" - ranks[{0}].Nickname : {1}" + Environment.NewLine, i, ranks[i].Nickname);
        sb.AppendFormat(" - ranks[{0}].ProfileImage : {1}" + Environment.NewLine, i, ranks[i].ProfileImage);
    }
 
    sb.AppendFormat(" - rankTotalCount : {0}", rankTotalCount);

    Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

If an error occurs while the StovePC.GetRank method is running, it calls the OnError callback.
You can check for external errors through the ExternalError field of the StovePCError structure.

ExternalError Description
1251 Invalid Parameter
1252 CannotFindData
3603 ErrorLeaderBoardNotFound
3631 ErrorMembershipAPI
500 External Server Error

# Integrating pop-ups

The PC SDK provides APIs to integrate popups into your game.
Pop-ups supported by PC SDK include automatic, manual, news, coupon, and community.
The PC SDK provides data for popups to the game. The game creates a pop-up view using the provided data.
Each popup is defined as follows.

  • Automatic pop-up: Pop-up that is most exposed on the game lobby screen and shows advertisements and events
  • Manual pop-up: Pop-up showing registered events corresponding to the resource key -News pop-up: A pop-up that collects and shows announcement posts at once
  • Coupon pop-up: Pop-up showing the coupon registration page
  • Community popup: Popup showing the game community page

In order to use the PC SDK popup API, the metadata registration of the popup integrated with Partners must be preceded.

# 1) Callback setting

In order to communicate with the PC SDK using the popup API, the game must define a delegate function to connect to the callback of the StovePCCallback class below.

  public class StovePCCallback
{
     public StovePCErrorDelegate OnError;
     public StovePCInitializationCompleteDelegate OnInitializationComplete;
     public StovePCTokenDelegate OnToken;
     public StovePCUserDelegate OnUser;
     public StovePCOwnershipDelegate OnOwnership;
  
     // Callback called when GetAutopopup processing is complete
     public StovePCAutoPopupDelegate OnAutoPopup;
         
     // Callback called when GetManualPopup processing is complete
     public StovePCManualPopupDelegate OnManualPopup;
  
     // Callback called when GetNewsPopup processing is complete
     public StovePCNewsPopupDelegate OnNewsPopup;
  
     // Callback called when GetCouponPopup processing is complete
     public StovePCCouponPopupDelegate OnCouponPopup;
  
     // Callback called when GetCommunityPopup processing is complete
     public StovePCcommunityPopupDelegate OnCommunityPopup;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Connect the delegate to the callback of the StovePCCallback class as in Integrating 2) Config, Callbak Settings.

// Create StovePCCallback class instance
this.callback = new StovePCCallback
{
     OnError = new StovePCErrorDelegate(this.OnError),
     OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
     OnToken = new StovePCTokenDelegate(this.OnToken),
     OnUser = new StovePCUserDelegate(this.OnUser),
     OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership),
  
     // pop-up
     OnAutoPopup = new StovePCAutoPopupDelegate(this.OnAutoPopup),
     OnManualPopup = new StovePCManualPopupDelegate(this.OnManualPopup),
     OnNewsPopup = new StovePCNewsPopupDelegate(this.OnNewsPopup),
     OnCouponPopup = new StovePCCouponPopupDelegate(this.OnCouponPopup),
     OnCommunityPopup = new StovePCCommunityPopupDelegate(this.OnCommunityPopup)
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

You are not required to implement the OnAutoPopup, OnManualPopup, OnNewsPopup, OnCouponPopup, OnCommunityPopup callbacks.
You only need to implement and connect the necessary callback functions according to the pop-up used in the game.

# 2) Game profile settings

Set game world and character information with StovePC.SetGameProfile function.
Set information is used in pop-ups, so it must be set before using pop-ups.
The validity of the game profile is not checked separately. Therefore, you must enter the correct value by proceeding with validation (null) when entering.
The entered game profile is only valid for the life cycle of PCSDK. That is, every time PCSDK is initialized, StovePC.SetGameProfile function is called
You need to set the game world and character information.

// input parameters
// string worldId: the game's world identifier
// long characterNo: character identifier
StovePCResult result = StovePC.SetGameProfile("WORLD_ID", CHARACTER_NO);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7
8

# 3) Get automatic pop-up information

Search information about auto popup with StovePC.GetAutoPopup function.

StovePCResult result = StovePC.GetAutoPopup();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

When the StovePC.GetAutoPopup function is successfully processed, the OnAutoPopup callback is called.
The StovePCAutoPopup structure passed to the callback contains the URL to the auto-popup.
The StovePCPopupRequestHeader structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.

private void OnAutoPopup(StovePCAutoPopup[] autoPopups, StovePCPopupRequestHeader[] headers)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnAutoPopup");
     sb.AppendFormat(" - autoPopups.Length : {0}" + Environment.NewLine, autoPopups.Length);
 
     for (int i = 0; i < autoPopups.Length; i++)
     {
         sb.AppendFormat(" - autoPopups[{0}].Origin : {1}" + Environment.NewLine, i, autoPopups[i].Origin);
         sb.AppendFormat(" - autoPopups[{0}].Id : {1}" + Environment.NewLine, i, autoPopups[i].Id.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Url : {1}" + Environment.NewLine, i, autoPopups[i].Url);

         // ADD 2.6.0 start
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.CloseButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.CloseButton.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.NavigationBar : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.NavigationBar.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.BackButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.BackButton.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.ForwardButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.ForwardButton.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.RefreshButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.RefreshButton.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.HomeButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.HomeButton.ToString());
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.Visible.DisallowedButton : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.Visible.DisallowedButton.ToString());

         sb.AppendFormat(" - autoPopups[{0}].Control.UI.DisallowedDay : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.DisallowedDay.ToString());

         sb.AppendFormat(" - autoPopups[{0}].Control.UI.CloseButtonImage.Normal.FileUrl : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.CloseButtonImage.Normal.FileUrl);
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.CloseButtonImage.Normal.FileId : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.CloseButtonImage.Normal.FileId);
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.CloseButtonImage.Pressed.FileUrl : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.CloseButtonImage.Pressed.FileUrl);
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.CloseButtonImage.Pressed.FileId : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.CloseButtonImage.Pressed.FileId);
         sb.AppendFormat(" - autoPopups[{0}].Control.UI.CloseButtonImage.Type : {1}" + Environment.NewLine, i, autoPopups[i].Control.UI.CloseButtonImage.Type.ToString());
         // 2.6.0 End
     }
 
     sb.AppendFormat(" - headers.Length : {0}" + Environment.NewLine, headers.Length);
 
     for (int i = 0; i < headers.Length; i++)
     {
         sb.AppendFormat(" - headers[{0}].Name : {1}" + Environment.NewLine, i, headers[i].Name);
         sb.AppendFormat(" - headers[{0}].Value : {1}", i, headers[i].Value);
 
         if (i < headers.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

Precautions

Even if the success callback (OnAutoPopup) is executed, the autoPopups callback parameter may be an empty array.
Before using the autoPopups callback parameter, you should check the length of the array before deciding whether or not to display a popup.
In this case, check Partners' automatic pop-up settings.
The display order of auto popups must be the same as the order of autoPopups array elements.
For example, if your autoPopups array contains three elements [A,B,C], you should expose popups in A, B, C order.

If an error occurs while running StovePC.GetAutoPopup, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
403000 Invalid Access Error
400000 Wrong API usage Error
400001 Not Found Error
400002 Not Match Error
400003 Already exist
500001 Internal Interaction Error
900000 Unknown Service Error

# 4) Obtain manual pop-up information

Search information about manual popup with StovePC.GetManualPopup function.

// input parameters
// string resourceKey: Manual pop-up identifier registered by Partners
StovePCResult result = StovePC.GetManualPopup("RESOURCE_KEY");
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7

When the StovePC.GetManualPopup function is successfully processed, the OnManualPopup callback is called.
The StovePCManualPopup structure passed to the callback contains the URL to the manual popup.
The StovePCPopupRequestHeader structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.

private void OnManualPopup(StovePCManualPopup[] manualPopups, StovePCPopupRequestHeader[] headers)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnManualPopup");
 
     for (int i = 0; i < manualPopups.Length; i++)
     {
         sb.AppendFormat(" - manualPopups[{0}].Origin : {1}" + Environment.NewLine, i, manualPopups[i].Origin);
         sb.AppendFormat(" - manualPopups[{0}].ResourceKey : {1}" + Environment.NewLine, i, manualPopups[i].ResourceKey);
         sb.AppendFormat(" - manualPopups[{0}].Id : {1}" + Environment.NewLine, i, manualPopups[i].Id.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Url : {1}" + Environment.NewLine, i, manualPopups[i].Url);
        
         // ADD 2.6.0 Start
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.CloseButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.CloseButton.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.NavigationBar : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.NavigationBar.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.BackButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.BackButton.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.ForwardButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.ForwardButton.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.RefreshButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.RefreshButton.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.HomeButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.HomeButton.ToString());
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.Visible.DisallowedButton : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.Visible.DisallowedButton.ToString());

         sb.AppendFormat(" - manualPopups[{0}].Control.UI.DisallowedDay : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.DisallowedDay.ToString());

         sb.AppendFormat(" - manualPopups[{0}].Control.UI.CloseButtonImage.Normal.FileUrl : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.CloseButtonImage.Normal.FileUrl);
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.CloseButtonImage.Normal.FileId : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.CloseButtonImage.Normal.FileId);
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.CloseButtonImage.Pressed.FileUrl : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.CloseButtonImage.Pressed.FileUrl);
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.CloseButtonImage.Pressed.FileId : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.CloseButtonImage.Pressed.FileId);
         sb.AppendFormat(" - manualPopups[{0}].Control.UI.CloseButtonImage.Type : {1}" + Environment.NewLine, i, manualPopups[i].Control.UI.CloseButtonImage.Type.ToString());
         // 2.6.0 End
     }
 
     sb.AppendFormat(" - headers.Length : {0}" + Environment.NewLine, headers.Length);
 
     for (int i = 0; i < headers.Length; i++)
     {
         sb.AppendFormat(" - headers[{0}].Name : {1}" + Environment.NewLine, i, headers[i].Name);
         sb.AppendFormat(" - headers[{0}].Value : {1}", i, headers[i].Value);
 
         if (i < headers.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

Precautions

Even if the success callback (OnManualPopup) is executed, the manualPopups callback parameter may be an empty array.
Before using the manualPopups callback parameter, you should first check the length of the array and decide whether or not to display a popup.
In this case, check the manual pop-up settings of Partners.
The exposure order of manual popups must be the same as the order of manualPopups array elements.
For example, if the manualPopups array contains three elements [A,B,C], then we need to expose popups in A, B, C order.

If an error occurs while running StovePC.GetManualPopup function, OnError callback will be called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
403000 Invalid Access Error
400000 Wrong API usage Error
400001 Not Found Error
400002 Not Match Error
400003 Already exist
500001 Internal Interaction Error
900000 Unknown Service Error

# 5) Get news pop-up information

Retrieve information about news popup with StovePC.GetNewsPopup function.

StovePCResult result = StovePC.GetNewsPopup();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

When the StovePC.GetNewsPopup function is successfully processed, the OnNewsPopup callback is called.
The StovePCNewsPopup structure passed to the callback contains the URL to the newspopup.
The StovePCPopupRequestHeader structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.

private void OnNewsPopup(StovePCNewsPopup newsPopup, StovePCPopupRequestHeader[] headers)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnNewsPopup");
     sb.AppendFormat(" - newsPopup.Origin : {0}" + Environment.NewLine, newsPopup.Origin);
     sb.AppendFormat(" - newsPopup.Id : {0}" + Environment.NewLine, newsPopup.Id.ToString());
     sb.AppendFormat(" - newsPopup.Url : {0}" + Environment.NewLine, newsPopup.Url);
    
     // ADD 2.6.0 Start
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.CloseButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.CloseButton.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.NavigationBar : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.NavigationBar.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.BackButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.BackButton.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.ForwardButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.ForwardButton.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.RefreshButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.RefreshButton.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.HomeButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.HomeButton.ToString());
     sb.AppendFormat(" - newsPopup.Control.UI.Visible.DisallowedButton : {0}" + Environment.NewLine, newsPopup.Control.UI.Visible.DisallowedButton.ToString());

     sb.AppendFormat(" - newsPopup.Control.UI.DisallowedDay : {0}" + Environment.NewLine, newsPopup.Control.UI.DisallowedDay.ToString());

     sb.AppendFormat(" - newsPopup.Control.UI.CloseButtonImage.Normal.FileUrl : {0}" + Environment.NewLine, newsPopup.Control.UI.CloseButtonImage.Normal.FileUrl);
     sb.AppendFormat(" - newsPopup.Control.UI.CloseButtonImage.Normal.FileId : {0}" + Environment.NewLine, newsPopup.Control.UI.CloseButtonImage.Normal.FileId);
     sb.AppendFormat(" - newsPopup.Control.UI.CloseButtonImage.Pressed.FileUrl : {0}" + Environment.NewLine, newsPopup.Control.UI.CloseButtonImage.Pressed.FileUrl);
     sb.AppendFormat(" - newsPopup.Control.UI.CloseButtonImage.Pressed.FileId : {0}" + Environment.NewLine, newsPopup.Control.UI.CloseButtonImage.Pressed.FileId);
     sb.AppendFormat(" - newsPopup.Control.UI.CloseButtonImage.Type : {0}" + Environment.NewLine, newsPopup.Control.UI.CloseButtonImage.Type.ToString());
     // 2.6.0 End
 
     sb.AppendFormat(" - headers.Length : {0}" + Environment.NewLine, headers.Length);
 
     for (int i = 0; i < headers.Length; i++)
     {
         sb.AppendFormat(" - headers[{0}].Name : {1}" + Environment.NewLine, i, headers[i].Name);
         sb.AppendFormat(" - headers[{0}].Value : {1}", i, headers[i].Value);
 
         if (i < headers.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Precautions

Even if the success callback (OnNewsPopup) is executed, newsPopup callback parameter properties may be default values (empty string or 0).
After checking the Url property of the newsPopup callback parameter, you should decide whether or not to open a popup. In this case, check the news pop-up settings of Partners.

If an error occurs while executing StovePC.GetNewsPopup, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
403000 Invalid Access Error
400000 Wrong API usage Error
400001 Not Found Error
400002 Not Match Error
400003 Already exist
500001 Internal Interaction Error
900000 Unknown Service Error

# 6) Get coupon pop-up information

Get coupon popup information with the StovePC.GetCouponPopup function.

StovePCResult result = StovePC.GetCouponPopup();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

When the StovePC.GetCouponPopup function is successfully processed, the OnCouponPopup callback is called.
The StovePCCouponPopup structure passed to the callback contains the URL to the coupon popup.
The StovePCPopupRequestHeader structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.

private void OnCouponPopup(StovePCCouponPopup couponPopup, StovePCPopupRequestHeader[] headers)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnCouponPopup");
     sb.AppendFormat(" - couponPopup.Url : {0}" + Environment.NewLine, couponPopup.Url);
    
     // ADD 2.6.0 Start
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.CloseButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.CloseButton.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.NavigationBar : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.NavigationBar.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.BackButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.BackButton.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.ForwardButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.ForwardButton.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.RefreshButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.RefreshButton.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.HomeButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.HomeButton.ToString());
     sb.AppendFormat(" - couponPopup.Control.UI.Visible.DisallowedButton : {0}" + Environment.NewLine, couponPopup.Control.UI.Visible.DisallowedButton.ToString());

     sb.AppendFormat(" - couponPopup.Control.UI.DisallowedDay : {0}" + Environment.NewLine, couponPopup.Control.UI.DisallowedDay.ToString());

     sb.AppendFormat(" - couponPopup.Control.UI.CloseButtonImage.Normal.FileUrl : {0}" + Environment.NewLine, couponPopup.Control.UI.CloseButtonImage.Normal.FileUrl);
     sb.AppendFormat(" - couponPopup.Control.UI.CloseButtonImage.Normal.FileId : {0}" + Environment.NewLine, couponPopup.Control.UI.CloseButtonImage.Normal.FileId);
     sb.AppendFormat(" - couponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl : {0}" + Environment.NewLine, couponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl);
     sb.AppendFormat(" - couponPopup.Control.UI.CloseButtonImage.Pressed.FileId : {0}" + Environment.NewLine, couponPopup.Control.UI.CloseButtonImage.Pressed.FileId);
     sb.AppendFormat(" - couponPopup.Control.UI.CloseButtonImage.Type : {0}" + Environment.NewLine, couponPopup.Control.UI.CloseButtonImage.Type.ToString());
     // 2.6.0 End
 
     sb.AppendFormat(" - headers.Length : {0}" + Environment.NewLine, headers.Length);
 
     for (int i = 0; i < headers.Length; i++)
     {
         sb.AppendFormat(" - headers[{0}].Name : {1}" + Environment.NewLine, i, headers[i].Name);
         sb.AppendFormat(" - headers[{0}].Value : {1}", i, headers[i].Value);
 
         if (i < headers.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

If an error occurs while running the StovePC.GetCouponPopup function, the OnError callback is called.

# 7) Get community pop-up information

Get community popup information with the StovePC.GetCommunityPopup function.

StovePCResult result = StovePC.GetCommunityPopup();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

When the StovePC.GetCommunityPopup function is successfully processed, the OnCommunityPopup callback is called.
The StovePCCommunityPopup structure passed to the callback contains the URL to the community popup.
The StovePCPopupRequestCookie structure passed to the callback contains the cookie name/value pair to be set when requesting the URL.

private void OnCommunityPopup(StovePCCommunityPopup communityPopup, StovePCPopupRequestCookie[] cookies)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnCommunityPopup");
     sb.AppendFormat(" - communityPopup.Url : {0}" + Environment.NewLine, communityPopup.Url);
    
     // ADD 2.6.0 Start
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.CloseButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.CloseButton.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.NavigationBar : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.NavigationBar.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.BackButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.BackButton.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.ForwardButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.ForwardButton.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.RefreshButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.RefreshButton.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.HomeButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.HomeButton.ToString());
     sb.AppendFormat(" - communityPopup.Control.UI.Visible.DisallowedButton : {0}" + Environment.NewLine, communityPopup.Control.UI.Visible.DisallowedButton.ToString());

     sb.AppendFormat(" - communityPopup.Control.UI.DisallowedDay : {0}" + Environment.NewLine, communityPopup.Control.UI.DisallowedDay.ToString());

     sb.AppendFormat(" - communityPopup.Control.UI.CloseButtonImage.Normal.FileUrl : {0}" + Environment.NewLine, communityPopup.Control.UI.CloseButtonImage.Normal.FileUrl);
     sb.AppendFormat(" - communityPopup.Control.UI.CloseButtonImage.Normal.FileId : {0}" + Environment.NewLine, communityPopup.Control.UI.CloseButtonImage.Normal.FileId);
     sb.AppendFormat(" - communityPopup.Control.UI.CloseButtonImage.Pressed.FileUrl : {0}" + Environment.NewLine, communityPopup.Control.UI.CloseButtonImage.Pressed.FileUrl);
     sb.AppendFormat(" - communityPopup.Control.UI.CloseButtonImage.Pressed.FileId : {0}" + Environment.NewLine, communityPopup.Control.UI.CloseButtonImage.Pressed.FileId);
     sb.AppendFormat(" - communityPopup.Control.UI.CloseButtonImage.Type : {0}" + Environment.NewLine, communityPopup.Control.UI.CloseButtonImage.Type.ToString());
     // 2.6.0 End
    
     sb.AppendFormat(" - cookies.Length : {0}" + Environment.NewLine, cookies.Length);
 
     for (int i = 0; i < cookies.Length; i++)
     {
         sb.AppendFormat(" - cookies[{0}].Name : {1}" + Environment.NewLine, i, cookies[i].Name);
         sb.AppendFormat(" - cookies[{0}].Value : {1}", i, cookies[i].Value);
 
         if (i < cookies.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

If an error occurs while running the StovePC.GetCommunityPopup function, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
13008 Mandatory Parameter missing
90001 AccessToken invalid
40101 Invalid token

# 8) Disable pop-ups 2.6.0

With the StovePC.SetPopupDisallowed function, set a specific pop-up not to be displayed for a certain period of time.
If the game directly implements the PC SDK pop-up UI, configure the UI by referring to the Control.UI.Visible.DisallowedButton value of the pop-up UI information
Call StovePC.SetPopupDisallowed function from button click handler.
When calling the StevePC.SetPopupDisallowed method, the days parameter uses the Control.UI.DisallowedDay value of the popup information.
If pop-up disallow is set, the relevant pop-up information will not be searched during the disallow period.

// input parameters
// int popupId : Popup identifier issued by Partners
// int days : the number of days of disallowance registered by Partners (once) or -1 (don't look again)
// int days : Unacceptable period registered by Partners (in days)
StovePCResult result = StovePC.SetPopupDisallowed(POPUP_ID, DAYS);
if (result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7
8
9

# Integrate billing 2.6.0

The PC SDK provides APIs to integrate Stove Platform's billing service into games. There is a shop as a billing service.
A typical scenario for a store is below. It may vary slightly depending on the game situation (e.g., whether or not there is a game server).

  • Information for store configuration is acquired through store category search and product search APIs.
  • The game organizes the store through the acquired category and product information and displays the UI.
  • To purchase each product, call the purchase start API.
    • In the case of a product with a selling price of 0
      • The purchase is completed when the purchase start API response is received.
    • For products with a selling price greater than 0
      • Obtain the one-time payment URL from the response of the purchase start API.
      • The game browses the one-time payment URL with an external browser. Supported browsers: Chrome (75+), Edge (42+)
      • It will complete the subsequent payment process through the web page.
  • When the payment is complete, the game calls the Purchase Status Check API to check the purchase status.
  • If the payment is confirmed to have been completed, usually, the game will provide the product.
  • You can check the product purchase history (whether purchased more than once) through the purchase verification API.
  • You can restore items through the library inquiry API.

To use the PC SDK billing service API, you must register the metadata of the billing service through Partners in advance.
Also, if you use the store through the PC SDK, you must pass the ShopKey issued by Partners to the 'StovePCConfig.ShopKey' field.
It will return an error will if you call the billing service API without ShopKey settings.

The game must check whether you agree to the terms of service every time you open the store.
If the game user does not agree to the service terms and conditions, open the browser using the terms and conditions agreement page URL provided by PCSDK so that the game user can agree to the service terms and conditions.
When a game user agrees to the terms of service and opens the store, he or she enters the store.

PC SDK operates an internal cache for store support.

Through the isRefresh parameter of the StovePC.FetchProducts method, you can determine whether to retrieve the product information from the cache or via Web API.
The product information retrieved through the Web API is updated in whole or in part (by category) in the cache, and then the product information is passed to the game as a callback.
(However, if the cache is empty, the product information is retrieved through the Web API and updated to the cache regardless of the value of the isRefresh parameter.)
In addition, the PC SDK updates the purchase/sale quantity and purchase status of each product in the cache through the Web API response when you call the StovePC.ConfirmPurchase method.

# (Example) Flow chart of billing integration

confirm confirm

  1. Initialize PC_SDK when starting the game
    • Initialize IAP through StovePC.IAPInitialize function.
    • When IAP is initialized, the entire item list is retrieved and stored in the built-in cache.
  2. Handling non-payment inquiries when entering the in-game shop page (optional)
    • If there are unpaid items after completing payment through StovePC.FetchInventory storage box inquiry, re-delivery is processed.
  3. After entering the store, search the category list for store composition.
    • Search categories in the store through StovePC.FetchShopCategories function.
  4. Search the item information through the category information in the store inquired in number 3.
    • Search product information included in the category through StovePC.FetchProducts function.
  5. Select an item to purchase from the store.
    • Purchase product information must be composed directly in an array. (ProductId/SalePrice/Quantity)
    • Quantity must be specified as 1.
  6. Search for one-time payment URL information to start product purchase.
    • Search the URL information of the one-time payment window through the StovePC.StartPurchase function.
  7. Process the product payment information pop-up within the game. (It must be processed to check the payment result in an external browser.)
  8. Pop up an external browser with the one-time payment URL information obtained through step 6.
  9. Proceed with product payment through the payment window of Stove billing.
    • Close the browser after payment is completed in the payment window.
  10. When you click the "Payment Complete" button on the product payment information pop-up created in step 7 in-game, the purchase status information is searched.
    • Search information on the payment status through the StovePC.ConfirmPurchase function.
    • After checking the payment completion status, close the pop-up and return to the store page.
  11. The purchase flow is complete.

reference

If the Stove payment is not in progress through an external browser and the payment result is not known through StovePC.StartPurchase
When entering the store page (2 times), the item is reissued through the StovePC.FetchInventory storage box inquiry.


The sequence diagram below shows a hypothetical store operation scenario.
This is an example of a general case and may differ slightly depending on the game situation (e.g. store category structure, store UI creation time, etc.).

  • PCSDK IAP initialization
  • Check to accept the Terms of Service
  • Open shop
  • Purchase goods
  • Check product purchase status
  • Verification of product purchase history
  • Handle item restoration

# 1) Callback setting

To communicate with the PC SDK using the billing service API, the game must define a delegate function to connect to the callback of the StovePCCallback class below.

public class StovePCCallback
{
     public StovePCErrorDelegate OnError;
     public StovePCInitializationCompleteDelegate OnInitializationComplete;
     public StovePCTokenDelegate OnToken;
     public StovePCUserDelegate OnUser;
     public StovePCOwnershipDelegate OnOwnership;

     // Callback called when FetchShopCategories processing is complete
     public StovePCFetchShopCategoriesDelegate OnFetchShopCategories;

     // Callback called when FetchProducts processing is complete
     public StovePCFetchProductsDelegate OnFetchProducts;

     // Callback called when StartPurchase processing is complete
     public StovePCStartPurchaseDelegate OnStartPurchase;

     // Callback called when ConfirmPurchase processing is complete
     public StovePCConfirmPurchaseDelegate OnConfirmPurchase;

     // Callback called when FetchInventory processing is complete
     public StovePCFetchInventoryDelegate OnFetchInventory;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Connect the delegate to the callback of the StovePCCallback class as in Integrating 2) Config, Callback Settings.

// Create StovePCCallback class instance
this.callback = new StovePCCallback
{
     OnError = new StovePCErrorDelegate(this.OnError),
     OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
     OnToken = new StovePCTokenDelegate(this.OnToken),
     OnUser = new StovePCUserDelegate(this.OnUser),
     OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership),

     // Terms of Service
     OnFetchTermsAgreement = new StovePCFetchTermsAgreementDelegate(this.OnFetchTermsAgreement),
   
     // billing service
     OnFetchShopCategories = new StovePCFetchShopCategoriesDelegate(this.OnFetchShopCategories),
     OnFetchProducts = new StovePCFetchProductsDelegate(this.OnFetchProducts),
     OnStartPurchase = new StovePCStartPurchaseDelegate(this.OnStartPurchase),
     OnConfirmPurchase = new StovePCConfirmPurchaseDelegate(this.OnConfirmPurchase),
     OnFetchInventory = new StovePCFetchInventoryDelegate(this.OnFetchInventory)
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

You are not required to implement the OnFetchTermsAgreement, OnFetchShopCategories, OnFetchProducts, OnStartPurchase, OnConfirmPurchase, OnFetchInventory callbacks.
You only need to connect the store when the game needs it.
However, for the store function, all 5 callbacks must be implemented and connected.

# 2) Initialize IAP

If the game decides to use PCSDK to provide billing service, try initializing billing with the StovePC.IAPInitialize function with the ShopKey factor value of the store key issued by the stove.
When billing initialization is attempted, the product list registered on the Stove platform is automatically retrieved and stored in the Stove PCSDK internal cache.
Call the StovePC.IAPInitialize function, and if it fails, send the error details to the StovePCResult and OnError callbacks.

// input parameters
// string shopKey : shopKey issued by the stove
StovePCResult result = StovePC.IAPInitialize(YOUR_SHOP_KEY);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7
ExternalError Description
500 Internal Server Error
50001 Store does not exist, or is under maintenance
50002 Product does not exist or is unavailable for sale
999999 undefined error

# 3) Game profile settings

Set game world and character information with StovePC.SetGameProfile function.
This is to determine the level of the product purchasing entity. The PC SDK prioritizes the purchaser of the product as follows.

  • Character No. > Guid > Member No.

When character information is set through the StovePC.SetGameProfile function, PC SDK proceeds with purchase based on Character No. when purchasing a product.
On the other hand, if character information is not set through StovePC.SetGameProfile function, PC SDK proceeds with purchase based on Guid or Member No.
Therefore, in order to ensure that the purchasing subject is properly applied when purchasing a product, you should consider whether to call the StovePC.SetGameProfile API before calling the billing service API of the PC SDK.
Normally, StovePC.SetGameProfile function only needs to be called once per world/character change.

# 4) Check whether you agree to the service terms and conditions

Use the StovePC.FetchTermsAgreement method to retrieve the user's service terms and conditions agreement information for the game.

StovePCResult result = StovePC.FetchTermsAgreement();
if(result == StovePCResult.NoError)
{
     // Success processing
}
1
2
3
4
5

If the StovePC.FetchTermsAgreement method is processed successfully, the OnFetchTermsAgreement callback is called.
The StovePCTermsAgreement structure passed to the callback contains meta information about the terms and conditions agreement.

  • StovePCShopCategory.GameId: Game ID
  • StovePCShopCategory.Result: Whether you agree to the service terms and conditions
  • StovePCShopCategory.Region: Region code
  • StovePCShopCategory.AgreementUrl: Terms of Service agreement agreement page Url
private void OnFetchTermsAgreement(StovePCTermsAgreement termsAgreement)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnFetchTermsAgreement");
     sb.AppendFormat(" - termsAgreement.GameId : {0}" + Environment.NewLine, termsAgreement.GameId);
     sb.AppendFormat(" - termsAgreement.Result : {0}" + Environment.NewLine, termsAgreement.Result.ToString());
     sb.AppendFormat(" - termsAgreement.Region : {0}", termsAgreement.Region);
     sb.AppendFormat(" - termsAgreement.AgreementUrl : {0}", termsAgreement.AgreementUrl);
    
     Debug.Log(sb.ToString());
    
     if(termsAgreement.Result == false)
     {
         // Open external browser
     Application.OpenURL(termsAgreement.AgreementUrl);
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

If an error occurs during execution of the StovePC.FetchTermsAgreement method, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
400 Bad request information
500 System Error
70898 Invalid data
70899 Invalid value exists in parameter
70800 No terms and conditions exist
70804 GS API call error
70805 GUID API call error
70806 Service not found
70807 Undefined error occurred in GUID API
40103 Token expiration

# 5) Get store category information

The StovePC.FetchShopCategories function retrieves store category information for the game.
Category information includes the ID of the parent category, so you can organize your store in a hierarchical structure.

StovePCResult result = StovePC.FetchShopCategories();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

When the StovePC.FetchShopCategories function is successfully processed, the OnFetchShopCategories callback is called.
The StovePCShopCategory structure passed to the callback contains meta information about the store category.

  • StovePCShopCategory.CategoryId : Category ID
  • StovePCShopCategory.ParentCategoryId: Parent Category ID
  • StovePCShopCategory.DisplayNo: Category order
  • StovePCShopCategory.Name: Category name
  • StovePCShopCategory.Depth: category depth (1 for top category)
private void OnFetchShopCategories(StovePCShopCategory[] categories)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnFetchShopCategories");
     sb.AppendFormat(" - categories.Length : {0}" + Environment.NewLine, categories.Length);

     for (int i = 0; i < categories.Length; i++)
     {
         sb.AppendFormat(" - categories[{0}].CategoryId : {1}" + Environment.NewLine, i, categories[i].CategoryId);
         sb.AppendFormat(" - categories[{0}].ParentCategoryId : {1}" + Environment.NewLine, i, categories[i].ParentCategoryId);
         sb.AppendFormat(" - categories[{0}].DisplayNo : {1}" + Environment.NewLine, i, categories[i].DisplayNo.ToString());
         sb.AppendFormat(" - categories[{0}].Name : {1}" + Environment.NewLine, i, categories[i].Name);
         sb.AppendFormat(" - categories[{0}].Depth : {1}", i, categories[i].Depth.ToString());
    
         if (i < categories.Length - 1)
               sb. AppendFormat(Environment. NewLine);
     }
    
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

The OnError callback is called if an error occurs while running the StovePC.FetchShopProducts function.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
500 Internal Server Error
999999 undefined error

# 6) Get product information

Retrieve product information for the game with StovePC.FetchProducts function.

// input parameters
// string categoryId : Category identifier registered by Partners (when passing an empty string, search all categories)
// bool isRefresh : If true, search Web API, if false, search PC SDK Cache
StovePCResult result = StovePC.FetchProducts("CATEGORY_ID", IS_REFRESH);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7
8

When the StovePC.FetchProducts function is successfully processed, the OnFetchProducts callback is called.
The StovePCProduct structure passed to the callback contains meta information about the product.

  • StovePCProduct.ProductId : Product ID
  • StovePCProduct.GameItemId : In-game item ID mapped to product ID
  • StovePCProduct.Name : Product name
  • StovePCProduct.Description : Product description
  • StovePCProduct.Quantity: Quantity of each product
  • StovePCProduct.ProductTypeCode : Product type code (1: game product, 2: in-game product, 3: package item)
  • StovePCProduct.CategoryId : Category ID
  • StovePCProduct.CurrencyCode : Currency code
  • StovePCProduct.Price: The list price of the product (if the CurrencyCode is equal to "KRW", the decimal point is omitted; if it is different, it is indicated to the second decimal place)
  • StovePCProduct.SalePrice: Product sales price (when displaying, if the CurrencyCode is equal to "KRW", the decimal point is omitted; if it is different, it is indicated to the second decimal place)
  • StovePCProduct.IsDiscount: Whether to discount
  • StovePCProduct.DiscountType : Discount type (1: flat rate, 2: flat rate)
  • StovePCProduct.DiscountTypeValue: Discount value
  • StovePCProduct.DiscountBeginDate : Discount start date (UTC+0)
  • StovePCProduct.DiscountEndDate : Discount end date (UTC+0)
  • StovePCProduct.TotalQuantity : Total product sales quantity
  • StovePCProduct.MemberQuantity : Member purchase quantity
  • StovePCProduct.GuidQuantity: Guid purchase quantity (purchase quantity of product purchase subject [CharacterNo/Guid/MemberNo])
  • StovePCProduct.ThumbnailUrl : Representative product image
private void OnFetchProducts(StovePCProduct[] products)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnFetchProducts");
     sb.AppendFormat(" - products.Length : {0}" + Environment.NewLine, products.Length);
    
     for (int i = 0; i < products.Length; i++)
     {
         sb.AppendFormat(" - products[{0}].ProductId : {1}" + Environment.NewLine, i, products[i].ProductId.ToString());
         sb.AppendFormat(" - products[{0}].GameItemId : {1}" + Environment.NewLine, i, products[i].GameItemId);
         sb.AppendFormat(" - products[{0}].Name : {1}" + Environment.NewLine, i, products[i].Name);
         sb.AppendFormat(" - products[{0}].Discription : {1}" + Environment.NewLine, i, products[i].Discription);
         sb.AppendFormat(" - products[{0}].Quantity : {1}" + Environment.NewLine, i, products[i].Quantity.ToString());
         sb.AppendFormat(" - products[{0}].ProductTypeCode : {1}" + Environment.NewLine, i, products[i].ProductTypeCode.ToString());
         sb.AppendFormat(" - products[{0}].CategoryId : {1}" + Environment.NewLine, i, products[i].CategoryId);
         sb.AppendFormat(" - products[{0}].CurrencyCode : {1}" + Environment.NewLine, i, products[i].CurrencyCode);
         sb.AppendFormat(" - products[{0}].Price : {1}" + Environment.NewLine, i, products[i].CurrencyCode == "KRW" ? products[i].Price.ToString("F0" ) : products[i].Price.ToString("F2"));
         sb.AppendFormat(" - products[{0}].SalePrice : {1}" + Environment.NewLine, i, products[i].CurrencyCode == "KRW" ? products[i].SalePrice.ToString("F0" ) : products[i].SalePrice.ToString("F2"));
         sb.AppendFormat(" - products[{0}].IsDiscount : {1}" + Environment.NewLine, i, products[i].IsDiscount.ToString());
         sb.AppendFormat(" - products[{0}].DiscountType : {1}" + Environment.NewLine, i, products[i].DiscountType.ToString());
         sb.AppendFormat(" - products[{0}].DiscountTypeValue : {1}" + Environment.NewLine, i, products[i].DiscountTypeValue.ToString());
         sb.AppendFormat(" - products[{0}].DiscountBeginDate : {1}" + Environment.NewLine, i, products[i].DiscountBeginDate.ToString());
         sb.AppendFormat(" - products[{0}].DiscountEndDate : {1}" + Environment.NewLine, i, products[i].DiscountEndDate.ToString());
         sb.AppendFormat(" - products[{0}].TotalQuantity : {1}" + Environment.NewLine, i, products[i].TotalQuantity.ToString());
         sb.AppendFormat(" - products[{0}].MemberQuantity : {1}" + Environment.NewLine, i, products[i].MemberQuantity.ToString());
         sb.AppendFormat(" - products[{0}].GuidQuantity : {1}" + Environment.NewLine, i, products[i].GuidQuantity.ToString());
         sb.AppendFormat(" - products[{0}].ThumbnailUrl : {1}", i, products[i].ThumbnailUrl);

         if (i < products.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

If an error occurs while running the StovePC.FetchProducts function, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
500 Internal Server Error
50001 Store does not exist, or is under maintenance
50002 Product does not exist or is unavailable for sale
999999 undefined error

# 7) Start purchasing products

Start purchasing a product with StovePC.StartPurchase function.

// input parameters
// StovePCOrderProduct[] products : Order product information
StovePCResult result = StovePC.StartPurchase(products);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7

When the StovePC.StartPurchase function is successfully processed, the OnStartPurchase callback is called.
The StovePCPurchase structure passed to the callback contains meta information about product purchase.

  • StovePCPurchase.TransactionMasterNo: Transaction unique master number
  • StovePCPurchase.TempPaymentUrl : One-time payment URL
  • StovePCPurchase.PurchaseProgress : Purchase progress status
    • 1: Payment in progress (page displayed in external browser)
    • 2: Purchase completed (Payment is completed due to the purchase of a product with a selling price of 0, so it is not necessary to display the page in an external browser using TempPaymentUrl)

When necessary, the game browses the one-time payment URL through an external browser. Supported browsers: Chrome (75+), Edge (42+)

private void OnStartPurchase(StovePCPurchase purchase)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnStartPurchase");
     sb.AppendFormat(" - purchase.TransactionMasterNo : {0}" + Environment.NewLine, purchase.TransactionMasterNo.ToString());
     sb.AppendFormat(" - purchase.TempPaymentUrl : {0}" + Environment.NewLine, purchase.TempPaymentUrl);
     sb.AppendFormat(" - purchase.PurchaseProgress : {0}", purchase.PurchaseProgress);

     Debug.Log(sb.ToString());

     if(purchase. PurchaseProgress == 1)
     {
         // open external browser
         Application.OpenURL(purchase.TempPaymentUrl);
     }
     else if(purchase. PurchaseProgress == 2)
     {
         // Processing purchase completion (e.g. purchase completion message box)
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

If an error occurs while running the StovePC.StartPurchase function, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.
Normally, when the OnError callback is called for the StovePC.StartPurchase function call, the game exposes a message about the failure to the game user.
The table below provides a guide on what messages to display to game users.

| ExternalError | Description | Check the exposure message for game users | |:-------------|:-----------------------------|:- ------------------------------------| | 500 | Internal Server Error | This is a temporary phenomenon or the service is not smooth due to network reasons. | | 50001 | Store does not exist, or is under maintenance | The service is under maintenance, or the service does not exist. | | 50002 | Product does not exist or is unavailable for sale | This product cannot be purchased due to its condition. | | 50003 | non-exhibition products | This product is not currently on sale. | | 50004 | Products outside the sale period | This is not a product sale period. | | 50005 | Product price inconsistency (if product price is changed) | Product price information has been changed. | | 50009 | Exceeds the number of sales per member that can be purchased | The number of purchases per person has been exceeded. | | 50010 | Exceeds the total number of sales available for purchase | All prepared quantities have been sold. | | 50031 | Purchase quantity is '0' | Please enter at least one quantity to purchase. | | 999999 | undefined error | The service is not smooth due to other errors. |

# 8) Check product purchase status

Check the product purchase status with the StovePC.ConfirmPurchase function.

// input parameters
// Int64 transactionMasterNo : Unique transaction master number (obtained through the OnStartPurchase callback parameter StovePCPurchase.TransactionMasterNo)
StovePCResult result = StovePC.ConfirmPurchase(TRANSACTION_MASTER_NO);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7

When the 'StovePC.ConfirmPurchase' function is successfully processed, the OnConfirmPurchase callback is called.
The StovePCPurchaseProduct structure passed to the callback contains meta information about the purchased product, and the status callback parameter delivers the purchase status of the product.

  • StovePCPurchaseProduct.TotalQuantity : Total product sales quantity
  • StovePCPurchaseProduct.MemberQuantity : Member purchase quantity
  • StovePCPurchaseProduct.GuidQuantity: Guid purchase quantity (purchase quantity of product purchase subject [CharacterNo/Guid/MemberNo])

In the case of a game without a separate game server, if the purchase result is successful, the game may provide an item.
In the case of a game with a game server, the game server can receive a notification about the purchase and can provide the item at this time.

private void OnConfirmPurchase(StovePCPurchaseProduct[] products, bool status, string shopKey)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnConfirmPurchase");
     sb.AppendFormat(" - products.Length : {0}" + Environment.NewLine, products.Length);

     for (int i = 0; i < products.Length; i++)
     {
         sb.AppendFormat(" - products[{0}].ProductId : {1}" + Environment.NewLine, i, products[i].ProductId.ToString());
         sb.AppendFormat(" - products[{0}].CategoryId : {1}" + Environment.NewLine, i, products[i].CategoryId);
         sb.AppendFormat(" - products[{0}].TotalQuantity : {1}" + Environment.NewLine, i, products[i].TotalQuantity.ToString());
         sb.AppendFormat(" - products[{0}].MemberQuantity : {1}" + Environment.NewLine, i, products[i].MemberQuantity.ToString());
         sb.AppendFormat(" - products[{0}].GuidQuantity : {1}" + Environment.NewLine, i, products[i].GuidQuantity.ToString());
     }

     sb.AppendFormat(" - status : {0}" + Environment.NewLine, status.ToString());
     sb.AppendFormat(" - shopKey : {0}", shopKey);

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

reference

In the above sample code, string shopKey in the function is the same value as YOUR_SHOP_KEY called by StovePC_IAPInit function.

You need to send YOUR_SHOP_KEY with shopKey as an input parameter.

If an error occurs while running the StovePC.ConfirmPurchase function, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
500 Internal Server Error
999999 undefined error

# 9) Verification of product purchase history

Verify product purchase history with StovePC.VerifyPurchase function. The value of the IsPurchased field is true for products that have been purchased more than once.
Product purchase history verification is performed targeting the cache within the PC SDK.
At this time, if you explicitly enter the value of the categoryId parameter, only that category is searched, and if you enter an empty string ("") in the value of the categoryId parameter, all categories are searched.
Therefore, it may be advantageous in terms of search speed to accurately enter the category ID to search.

// input parameters
// string categoryId : Category ID to search for products
// long productId : Product ID
StovePCPurchaseVerification purchaseVerification = StovePC.VerifyPurchase("CATEGORY_ID", PRODUCT_ID);
if (purchaseVerification.Result == StovePCResult.NoError)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("VerifyPurchase Success");
     sb.AppendFormat(" - purchaseVerification.IsPurchased : {0}", purchaseVerification.IsPurchased);

     Debug.Log(sb.ToString());
}
else
{
     // handle failure
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

The StovePC.VerifyPurchase function returns a StovePCPurchaseVerification structure.
The returned StovePCPurchaseVerification structure contains the product purchase history.
Also included are error codes for function calls.

# 10) Search archives

Fetch Inventory with StovePC.FetchInventory function. Items that have been purchased are stored in the storage box.
You can process product payment by using the list of purchased products in the storage box.
Normally, games call the StovePC.ConfirmPurchase function to check the product purchase status and immediately deliver the product.
If the product information provided is lost due to an error, game reinstallation, etc., it can be used for recovery work using the storage box information.

StovePCResult result = StovePC. FetchInventory();
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5

If the StovePC.FetchInventory function is successfully processed, the OnFetchInventory callback is called.
The StovePCInventoryItem structure passed to the callback contains meta information about the purchased product.

  • StovePCInventoryItem.TransactionMasterNo: Transaction unique master number
  • StovePCInventoryItem.TransactionDetailNo: transaction specific detail number
  • StovePCInventoryItem.ProductId: Product ID
  • StovePCInventoryItem.GameItemId: In-game item ID mapped to product ID
  • StovePCInventoryItem.ProductName: Product name
  • StovePCInventoryItem.Quantity: Quantity of individual product
  • StovePCInventoryItem.ThumbnailUrl : Representative product image
private void OnFetchInventory(StovePCInventoryItem[] inventoryItems)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnFetchInventory");
     sb.AppendFormat(" - inventoryItems.Length : {0}" + Environment.NewLine, inventoryItems.Length);
    
     for (int i = 0; i < inventoryItems.Length; i++)
     {
         sb.AppendFormat(" - inventoryItems[{0}].TransactionMasterNo : {1}" + Environment.NewLine, i, inventoryItems[i].TransactionMasterNo.ToString());
         sb.AppendFormat(" - inventoryItems[{0}].TransactionDetailNo : {1}" + Environment.NewLine, i, inventoryItems[i].TransactionDetailNo.ToString());
         sb.AppendFormat(" - inventoryItems[{0}].ProductId : {1}" + Environment.NewLine, i, inventoryItems[i].ProductId.ToString());
         sb.AppendFormat(" - inventoryItems[{0}].GameItemId : {1}" + Environment.NewLine, i, inventoryItems[i].GameItemId);
         sb.AppendFormat(" - inventoryItems[{0}].ProductName : {1}" + Environment.NewLine, i, inventoryItems[i].ProductName);
         sb.AppendFormat(" - inventoryItems[{0}].Quantity : {1}" + Environment.NewLine, i, inventoryItems[i].Quantity.ToString());
         sb.AppendFormat(" - inventoryItems[{0}].ThumbnailUrl : {1}", i, inventoryItems[i].ThumbnailUrl);

         if (i < inventoryItems.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

If an error occurs while running the StovePC.FetchInventory function, the OnError callback is called.
External errors can be checked through the ExternalError field of the StovePCError structure.

ExternalError Description
500 Internal Server Error
999999 undefined error

# Integrating additional services

PC SDK provides API to integrate additional services into games.
Additional services supported by PC SDK include custom event log, PC SDK version inquiry, over-immersion prevention notification, shutdown notification, tracking clue inquiry.
Games can send custom in-game events (game logs) to the Stove platform. Also, the game can query the semantic version of the PC SDK currently in use.
PC SDK semantic version inquiry can be obtained as a return value, not a callback.
The Over Immersion Prevention Alert delivers a warning phrase about over immersion in the game through a callback every hour.
Shutdown notification is a system that restricts children under the age of 18 from using the game at a specific time per day of the week by their parents. When the requirements are met, notifications are delivered through callbacks up to 4 times.

# 1) Callback setting

In order to communicate with the PC SDK using the additional service API, the game must define a delegate function to connect to the callback pointer of the StovePCCallback structure below.

public class StovePCCallback
{
     public StovePCErrorDelegate OnError;
     public StovePCInitializationCompleteDelegate OnInitializationComplete;
     public StovePCTokenDelegate OnToken;
     public StovePCUserDelegate OnUser;
     public StovePCOwnershipDelegate OnOwnership;
  
     public StovePCStatDelegate OnStat;
     public StovePCSetStatDelegate OnSetStat;
     public StovePCAchievementDelegate OnAchievement;
     public StovePCAllAchievementDelegate OnAllAchievement;
     public StovePCRankDelegate OnRank;
 
     // Callback called when StashCustomEvent processing is complete
     public StovePCStashCustomEventDelegate OnStashCustomEvent;
    
     // ADD 2.6.0 Start
     // Callback that is called every hour to prevent over-immersion
     public StovePCOverImmersionDelegate OnOverImmersion;
    
     // Callback to be called on shutdown limit
     public StovePCShutdownDelegate OnShutdown;
     // 2.6.0 End
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Connect the delegate to the callback of the StovePCCallback class as in Integrating 2) Config, Callback Settings.

// Create StovePCCallback class instance
this.callback = new StovePCCallback
{
     OnError = new StovePCErrorDelegate(this.OnError),
     OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
     OnToken = new StovePCTokenDelegate(this.OnToken),
     OnUser = new StovePCUserDelegate(this.OnUser),
     OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership),
  
     // game support service
     OnStat = new StovePCStatDelegate(this.OnStat),
     OnSetStat = new StovePCSetStatDelegate(this.OnSetStat),
     OnAchievement = new StovePCAchievementDelegate(this.OnAchievement),
     OnAllAchievement = new StovePCAllAchievementDelegate(this.OnAllAchievement),
     OnRank = new StovePCRankDelegate(this.OnRank),
 
     //Extra service
     OnStashCustomEvent = new StovePCStashCustomEventDelegate(this.OnStashCustomEvent)
     // ADD 2.6.0 Start
     OnOverImmersion = new StovePCOverImmersionDelegate(this.OnOverImmersion);
     OnShutdown = new StovePCShutdownDelegate(this.OnShutdown);
     // 2.6.0 End
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

You are not required to implement the OnStashCustomEvent callback. You only need to connect if your game uses the custom event log feature.

warning

The OnOverImmersion callback must be implemented if legally required to prevent overimmersion/addiction to games.
The OnShutdown callback must be implemented if a selective shutdown is required by law.

# 2) Logging custom events

Log custom events (game logs) with StovePC.StashCustomEvent function.

// input parameters
// string name: event name
// string category1 : primary category name
// string category2: 2nd category name
// float simpleValue : simple value
// StovePCCustomEventParameter[] parameters : detailed parameter information
StovePCResult result = StovePC.StashCusomEvent("EVENT_NAME", "CATEGORY1", "CATEGORY2", 1.0f, parameters);
if(result == StovePCResult.NoError)
{
     // handle success
}
1
2
3
4
5
6
7
8
9
10
11

When the StovePC.StashCustomEvent function is successfully processed, the OnStashCustomEvent callback is called.
The StovePCCustomEvent structure passed to the callback contains the event name, primary category name, secondary category name, and simple values passed when calling the API.
The StovePCCustomEventParameter structure passed to the callback contains parameter information passed when calling the API.

void OnStashCustomEvent(StovePCCustomEvent customEvent, StovePCCustomEventParameter[] parameters)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnStashCustomEvent");
     sb.AppendFormat(" - customEvent.Name : {0}" + Environment.NewLine, customEvent.Name);
     sb.AppendFormat(" - customEvent.Category1 : {0}" + Environment.NewLine, customEvent.Category1);
     sb.AppendFormat(" - customEvent.Category2 : {0}" + Environment.NewLine, customEvent.Category2);
     sb.AppendFormat(" - customEvent.SimpleValue : {0}" + Environment.NewLine, customEvent.SimpleValue.ToString());
 
     sb.AppendFormat(" - parameters.Length : {0}" + Environment.NewLine, parameters.Length);
 
     for (int i = 0; i < parameters.Length; i++)
     {
         sb.AppendFormat(" - parameters[{0}].Name : {1}" + Environment.NewLine, i, parameters[i].Name);
         sb.AppendFormat(" - parameters[{0}].Value : {1}", i, parameters[i].Value);
 
         if (i < parameters.Length - 1)
             sb. AppendFormat(Environment. NewLine);
     }
 
     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

If an error occurs while running the StovePC_StashCustomEvent function, the OnError callback is called.

# 3) Get PC SDK semantic version

Use the StovePC.GetSDKVersion function to retrieve the version information of the PC SDK currently being linked.

string version = StovePC.GetSDKVersion();
if(version != "")
{
     // handle success
}
1
2
3
4
5

# 4) Prevention of excessive immersion in games 2.6.0

WARNING

The following features will be available after the release on May 30, 2023.

The OnOverImmersion callback is called every hour after starting the game.
The StovePCOverImmersion structure passed to the callback contains the following: The message. The elapsed time of using the game. The message's minimum exposure time (in seconds).
The message is translated based on the language set in the PC SDK.

private void OnOverImmersion(StovePCOverImmersion overImmersion)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnOverImmersion");
     sb.AppendFormat(" - overImmersion.Message : {0}" + Environment.NewLine, overImmersion.Message);
     sb.AppendFormat(" - overImmersion.ElapsedTimeInHours : {0}" + Environment.NewLine, overImmersion.ElapsedTimeInHours.ToString());
     sb.AppendFormat(" - overImmersion.MinExposureTimeInSeconds : {0}", overImmersion.MinExposureTimeInSeconds.ToString());

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10

# 4) Prevention of excessive immersion in games 2.6.0

The OnOverImmersion callback is called every hour after starting the game.
The StovePCOverImmersion structure passed to the callback contains the message, the elapsed time of using the game, and the minimum exposure time (in seconds) of the message.

  • StovePCOverImmersion.Message: Overimmersion message
  • StovePCOverImmersion.ElapsedTimeInHours: Elapsed time
  • StovePCOverImmersion.MinExposureTimeInSeconds : Minimum exposure time of message (in seconds)

The message is translated based on the language set in the PC SDK.

private void OnOverImmersion(StovePCOverImmersion overImmersion)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnOverImmersion");
     sb.AppendFormat(" - overImmersion.Message : {0}" + Environment.NewLine, overImmersion.Message);
     sb.AppendFormat(" - overImmersion.ElapsedTimeInHours : {0}" + Environment.NewLine, overImmersion.ElapsedTimeInHours.ToString());
     sb.AppendFormat(" - overImmersion.MinExposureTimeInSeconds : {0}", overImmersion.MinExposureTimeInSeconds.ToString());

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10

Guide to over-immersion messages

과몰입 메시지 : 게임을 플레이한 지 1 시간이 지났습니다. 과도한 게임이용은 정상적인 일상생활에 지장을 줄 수 있습니다.

# 5) Shut down 2.6.0

After starting the game, the OnShutdown callback is called based on the timetable registered in the shutdown system only for those subject to selective shutdown.
The OnShutdown callback can be called up to 4 times, and the time it is called and the actions to be taken in the game are as follows.

  • Shutdown event after successful PCSDK initialization
    • Shutdown notification 10 minutes ago: Shows only notification that you will be logged out after 10 minutes
    • Notification of shutdown 5 minutes ago: Shows only notification that you will be logged out after 5 minutes
    • Shutdown notification 1 minute ago: Displays only notification that you will be logged out after 1 minute
    • Shutdown Notification: Displays a notification that you will be logged out and ends the game immediately upon user confirmation

The StovePCShutdown structure passed to the callback contains the remaining time until shutdown, the message, and the message exposure time (in seconds).

  • StovePCShutdown.InadvanceTimeInMinutes: The remaining time (minutes) until the user shuts down. If 0, the game ends immediately.
  • StovePCShutdown.Message : Shutdown notification message
  • StovePCShutdown.ExposureTimeInSeconds: message exposure time (seconds)
private void OnShutdown(StovePCShutdown shutdown)
{
     StringBuilder sb = new StringBuilder();
     sb.AppendLine("OnShutdown");
     sb.AppendFormat(" - shutdown.InadvanceTimeInMinutes : {0}" + Environment.NewLine, shutdown.InadvanceTimeInMinutes.ToString());
     sb.AppendFormat(" - shutdown.Message : {0}" + Environment.NewLine, shutdown.Message);
     sb.AppendFormat(" - shutdown.ExposureTimeInSeconds : {0}", shutdown.ExposureTimeInSeconds.ToString());

     Debug.Log(sb.ToString());
}
1
2
3
4
5
6
7
8
9
10

Shutdown Message Information

10 minutes : 회원님은 게임 시간 선택제 적용 대상으로 10 분 후 게임 이용이 제한됩니다.
5 minutes : 회원님은 게임 시간 선택제 적용 대상으로 5 분 후 게임 이용이 제한됩니다.
1 minutes : 회원님은 게임 시간 선택제 적용 대상으로 1 분 후 게임 이용이 제한됩니다.
0 minutes : 회원님은 게임 시간 선택제 적용 대상으로 게임 이용이 제한되어 게임을 종료합니다.

Retrieve a set of clues for tracing stove platform logs with StovePC.GetTraceHint function.

StovePCTraceHint traceHint = StovePC.GetTraceHint();
if (traceHint.Result == StovePCResult.NoError)
{
     sb.AppendLine("GetTraceHint Success");
     sb.AppendFormat(" - traceHint.SessionId : {0}" + Environment.NewLine, traceHint.SessionId);
     sb.AppendFormat(" - traceHint.RefSessionId : {0}" + Environment.NewLine, traceHint.RefSessionId);
     sb.AppendFormat(" - traceHint.Uuid : {0}" + Environment.NewLine, traceHint.Uuid);
     sb.AppendFormat(" - traceHint.ServiceProtocol : {0}" + Environment.NewLine, traceHint.ServiceProtocol);
     sb.AppendFormat(" - traceHint.RefSourceType : {0}", traceHint.RefSourceType);
    
     Debug.Log(sb.ToString());
}
else
{
     // handle failure
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

The StovePC.GetTraceHint function returns a StovePCTraceHint structure.
The returned StovePCTraceHint structure includes the session ID and reference session ID.
Also included are error codes for function calls.

Last Updated: 7/26/2024, 8:22:06 AM