GS2-SeasonRating SDK for Game Engine API リファレンス
モデル
EzSeasonModel
シーズンモデル
GS2 ではレーティングアルゴリズムとして Glicko-2 を採用しています。
Glicko-2 には複数のパラメータがありますが、GS2-Matchmaking ではそれらを総合的に表す ボラティリティ という1つのパラメータに集約しています。
ボラティリティ は変化の大きさを表すパラメータで、値が大きいほどレーティングの値の変動量が大きくなります。
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
seasonModelId | string | ✓ | ~ 1024文字 | シーズンモデルGRN | |
name | string | ✓ | ~ 128文字 | シーズンモデル名 | |
metadata | string | ~ 128文字 | メタデータ | ||
tiers | List<EzTierModel> | ✓ | 1 ~ 100 items | ティアーリスト | |
experienceModelId | string | ✓ | ~ 1024文字 | 経験値モデルGRN |
EzTierModel
ティアーモデル
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
metadata | string | ~ 128文字 | メタデータ | ||
raiseRankBonus | int | ✓ | ~ 10000 | ランク昇格時にすぐにランク降格を防ぐために加算するボーナスポイント | |
minimumChangePoint | int | ✓ | ~ -1 | 負けた際に変動するレート値の最小値 | |
maximumChangePoint | int | ✓ | 1 ~ 99999999 | 勝った際に変動するレート値の最大値 |
EzGameResult
対戦結果
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
rank | int | ✓ | ~ 2147483646 | 順位 | |
userId | string | ✓ | ~ 128文字 | ユーザーID |
EzBallot
投票用紙
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
userId | string | ✓ | ~ 128文字 | ユーザーID | |
seasonName | string | ✓ | ~ 128文字 | レーティング計算に使用するシーズン名 | |
sessionName | string | ✓ | ~ 128文字 | 投票対象のセッション名 | |
numberOfPlayer | int | ✓ | 2 ~ 10 | 参加人数 |
EzSignedBallot
署名付の投票用紙
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
body | string | ✓ | ~ 1024文字 | 投票用紙の署名対象のデータ | |
signature | string | ✓ | ~ 256文字 | 投票用紙の署名 |
メソッド
getSeasonModel
シーズン名を指定してシーズンモデルを取得
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | |
seasonName | string | ✓ | ~ 128文字 | シーズンモデル名 |
Result
型 | 説明 | |
---|---|---|
item | EzSeasonModel | シーズンモデル |
実装例
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).SeasonModel(
seasonName: "mode1"
);
var item = await domain.ModelAsync();
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).SeasonModel(
seasonName: "mode1"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
)->SeasonModel(
"mode1" // seasonName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
値の変更イベントハンドリング
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).SeasonModel(
seasonName: "mode1"
);
// イベントハンドリングを開始
var callbackId = domain.Subscribe(
value => {
// 値が変化した時に呼び出される
// value には変更後の値が渡ってくる
}
);
// イベントハンドリングを停止
domain.Unsubscribe(callbackId);
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).SeasonModel(
seasonName: "mode1"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
)->SeasonModel(
"mode1" // seasonName
);
// イベントハンドリングを開始
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SeasonRating::Model::FSeasonModel> value) {
// 値が変化した時に呼び出される
// value には変更後の値が渡ってくる
}
);
// イベントハンドリングを停止
Domain->Unsubscribe(CallbackId);
Warning
このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。
ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。
そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
listSeasonModels
シーズンモデルの一覧を取得
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 |
Result
型 | 説明 | |
---|---|---|
items | List<EzSeasonModel> | シーズンモデルのリスト |
実装例
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var items = await domain.SeasonModelsAsync(
).ToListAsync();
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var it = domain.SeasonModels(
);
List<EzSeasonModel> items = new List<EzSeasonModel>();
while (it.HasNext())
{
yield return it.Next();
if (it.Error != null)
{
onError.Invoke(it.Error, null);
break;
}
if (it.Current != null)
{
items.Add(it.Current);
}
else
{
break;
}
}
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
);
const auto It = Domain->SeasonModels(
);
TArray<Gs2::UE5::SeasonRating::Model::FEzSeasonModelPtr> Result;
for (auto Item : *It)
{
if (Item.IsError())
{
return false;
}
Result.Add(Item.Current());
}
値の変更イベントハンドリング
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
// イベントハンドリングを開始
var callbackId = domain.SubscribeSeasonModels(
() => {
// リストの要素が変化した時に呼び出される
}
);
// イベントハンドリングを停止
domain.UnsubscribeSeasonModels(callbackId);
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var it = domain.SeasonModels(
);
List<EzSeasonModel> items = new List<EzSeasonModel>();
while (it.HasNext())
{
yield return it.Next();
if (it.Error != null)
{
onError.Invoke(it.Error, null);
break;
}
if (it.Current != null)
{
items.Add(it.Current);
}
else
{
break;
}
}
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
);
// イベントハンドリングを開始
const auto CallbackId = Domain->SubscribeSeasonModels(
[]() {
// リストの要素が変化した時に呼び出される
}
);
// イベントハンドリングを停止
Domain->UnsubscribeSeasonModels(CallbackId);
Warning
このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。
ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。
そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
createVote
投票用紙を作成
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | |
seasonName | string | ✓ | ~ 128文字 | シーズンモデル名 | |
sessionName | string | ✓ | UUID | ~ 128文字 | セッション名 |
accessToken | string | ✓ | ~ 128文字 | ユーザーID | |
numberOfPlayer | int | ✓ | 2 ~ 10 | 参加人数 | |
keyId | string | ✓ | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024文字 | 暗号鍵GRN |
Result
型 | 説明 | |
---|---|---|
item | EzBallot | 投票用紙 |
body | string | 署名対象のデータ |
signature | string | 署名データ |
実装例
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Ballot(
seasonName: "rating-0001",
sessionName: "gathering-0001",
numberOfPlayer: 4,
keyId: "key-0001"
);
var item = await domain.ModelAsync();
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Ballot(
seasonName: "rating-0001",
sessionName: "gathering-0001",
numberOfPlayer: 4,
keyId: "key-0001"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Ballot(
"rating-0001", // seasonName
"gathering-0001", // sessionName
4, // numberOfPlayer
"key-0001" // keyId
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
値の変更イベントハンドリング
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Ballot(
seasonName: "rating-0001",
sessionName: "gathering-0001",
numberOfPlayer: 4,
keyId: "key-0001"
);
// イベントハンドリングを開始
var callbackId = domain.Subscribe(
value => {
// 値が変化した時に呼び出される
// value には変更後の値が渡ってくる
}
);
// イベントハンドリングを停止
domain.Unsubscribe(callbackId);
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Ballot(
seasonName: "rating-0001",
sessionName: "gathering-0001",
numberOfPlayer: 4,
keyId: "key-0001"
);
var future = domain.Model();
yield return future;
var item = future.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Ballot(
"rating-0001", // seasonName
"gathering-0001", // sessionName
4, // numberOfPlayer
"key-0001" // keyId
);
// イベントハンドリングを開始
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SeasonRating::Model::FBallot> value) {
// 値が変化した時に呼び出される
// value には変更後の値が渡ってくる
}
);
// イベントハンドリングを停止
Domain->Unsubscribe(CallbackId);
Warning
このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。
ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。
そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
vote
対戦結果を投票します。
投票は最初の投票が行われてから5分以内に行う必要があります。
つまり、結果は即座に反映されず、投票開始からおよそ5分後または全てのプレイヤーが投票を行った際に結果が反映されます。
5分以内に全ての投票用紙を回収できなかった場合はその時点の投票内容で多数決をとって結果を決定します。
各結果の投票数が同一だった場合は結果は捨てられます(スクリプトで挙動を変更可)。
結果を即座に反映したい場合は、勝利した側の代表プレイヤーが投票用紙を各プレイヤーから集めて voteMultiple を呼び出すことで結果を即座に反映できます。
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | |
ballotBody | string | ✓ | ~ 1024文字 | 投票用紙の署名対象のデータ | |
ballotSignature | string | ✓ | ~ 256文字 | 投票用紙の署名 | |
gameResults | List<EzGameResult> | ~ 10 items | 投票内容。対戦を行ったプレイヤーグループ1に所属するユーザIDのリスト | ||
keyId | string | ✓ | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024文字 | 暗号鍵GRN |
Result
型 | 説明 | |
---|---|---|
item | EzBallot | 投票用紙 |
実装例
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var result = await domain.VoteAsync(
ballotBody: "ballotBody",
ballotSignature: "ballotSignature",
gameResults: new List<Gs2.Unity.Gs2SeasonRating.Model.EzGameResult> {
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 1,
UserId = "user-0001",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0002",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0003",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 3,
UserId = "user-0004",
},
},
keyId: "key-0001"
);
var item = await result.ModelAsync();
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var future = domain.VoteFuture(
ballotBody: "ballotBody",
ballotSignature: "ballotSignature",
gameResults: new List<Gs2.Unity.Gs2SeasonRating.Model.EzGameResult> {
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 1,
UserId = "user-0001",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0002",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0003",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 3,
UserId = "user-0004",
},
},
keyId: "key-0001"
);
yield return future;
if (future.Error != null)
{
onError.Invoke(future.Error, null);
yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
onError.Invoke(future2.Error, null);
yield break;
}
var result = future2.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
);
const auto Future = Domain->Vote(
"ballotBody", // ballotBody
"ballotSignature", // ballotSignature
[]
{
auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::SeasonRating::Model::FEzGameResult>>>();
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(1))
->WithUserId(TOptional<FString>("user-0001"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(2))
->WithUserId(TOptional<FString>("user-0002"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(2))
->WithUserId(TOptional<FString>("user-0003"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(3))
->WithUserId(TOptional<FString>("user-0004"))
);
return v;
}(), // gameResults
"key-0001" // keyId
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
// obtain changed values / result values
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError())
{
return Future2->GetTask().Error();
}
const auto Result = Future2->GetTask().Result();
voteMultiple
対戦結果をまとめて投票します。
ゲームに勝利した側が他プレイヤーの投票用紙を集めてまとめて投票するのに使用します。
『勝利した側』としているのは、敗北した側が自分たちが勝ったことにして報告することにインセンティブはありますが、その逆はないためです。
負けた側が投票用紙を渡してこない可能性がありますが、その場合も過半数の投票用紙があれば結果を通すことができます。
Request
型 | 必須 | デフォルト | 値の制限 | 説明 | |
---|---|---|---|---|---|
namespaceName | string | ✓ | ~ 128文字 | ネームスペース名 | |
signedBallots | List<EzSignedBallot> | ~ 10 items | 署名付の投票用紙リスト | ||
gameResults | List<EzGameResult> | ~ 10 items | 投票内容。対戦を行ったプレイヤーグループ1に所属するユーザIDのリスト | ||
keyId | string | ✓ | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024文字 | 暗号鍵GRN |
Result
型 | 説明 | |
---|---|---|
item | EzBallot | 投票用紙 |
実装例
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var result = await domain.VoteMultipleAsync(
signedBallots: new List<Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot> {
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
},
gameResults: new List<Gs2.Unity.Gs2SeasonRating.Model.EzGameResult> {
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 1,
UserId = "user-0001",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0002",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0003",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 3,
UserId = "user-0004",
},
},
keyId: "key-0001"
);
var item = await result.ModelAsync();
var domain = gs2.SeasonRating.Namespace(
namespaceName: "namespace-0001"
);
var future = domain.VoteMultipleFuture(
signedBallots: new List<Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot> {
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzSignedBallot() {
Body = "aaa",
Signature = "bbb",
},
},
gameResults: new List<Gs2.Unity.Gs2SeasonRating.Model.EzGameResult> {
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 1,
UserId = "user-0001",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0002",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 2,
UserId = "user-0003",
},
new Gs2.Unity.Gs2SeasonRating.Model.EzGameResult() {
Rank = 3,
UserId = "user-0004",
},
},
keyId: "key-0001"
);
yield return future;
if (future.Error != null)
{
onError.Invoke(future.Error, null);
yield break;
}
var future2 = future.Result.Model();
yield return future2;
if (future2.Error != null)
{
onError.Invoke(future2.Error, null);
yield break;
}
var result = future2.Result;
const auto Domain = Gs2->SeasonRating->Namespace(
"namespace-0001" // namespaceName
);
const auto Future = Domain->VoteMultiple(
[]
{
auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::SeasonRating::Model::FEzSignedBallot>>>();
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzSignedBallot>()
->WithBody(TOptional<FString>("aaa"))
->WithSignature(TOptional<FString>("bbb"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzSignedBallot>()
->WithBody(TOptional<FString>("aaa"))
->WithSignature(TOptional<FString>("bbb"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzSignedBallot>()
->WithBody(TOptional<FString>("aaa"))
->WithSignature(TOptional<FString>("bbb"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzSignedBallot>()
->WithBody(TOptional<FString>("aaa"))
->WithSignature(TOptional<FString>("bbb"))
);
return v;
}(), // signedBallots
[]
{
auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::SeasonRating::Model::FEzGameResult>>>();
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(1))
->WithUserId(TOptional<FString>("user-0001"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(2))
->WithUserId(TOptional<FString>("user-0002"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(2))
->WithUserId(TOptional<FString>("user-0003"))
);
v->Add(
MakeShared<Gs2::UE5::SeasonRating::Model::FEzGameResult>()
->WithRank(TOptional<int32>(3))
->WithUserId(TOptional<FString>("user-0004"))
);
return v;
}(), // gameResults
"key-0001" // keyId
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
// obtain changed values / result values
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError())
{
return Future2->GetTask().Error();
}
const auto Result = Future2->GetTask().Result();