Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea20ea6d51 | |||
| 3c590294c9 | |||
| d4bbafb314 |
@@ -3,3 +3,4 @@ obj/
|
|||||||
.vs/
|
.vs/
|
||||||
.idea/
|
.idea/
|
||||||
TestResults/
|
TestResults/
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
|
public class LoginViaCustomRequest
|
||||||
|
{
|
||||||
|
[JsonProperty("customData")]
|
||||||
|
public JToken? CustomData { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("key")]
|
||||||
|
public string? Key { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("language")]
|
||||||
|
public string? Language { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("nickname")]
|
||||||
|
public string? Nickname { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("region")]
|
||||||
|
public string? Region { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
|
public class LoginViaCustomResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("accessToken")]
|
||||||
|
public string? AccessToken { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("refreshToken")]
|
||||||
|
public string? RefreshToken { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Auth;
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
public class LoginViaDeviceRequest
|
public class LoginViaDeviceRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceId")]
|
[JsonProperty("deviceId")]
|
||||||
public string DeviceId { get; set; }
|
public string? DeviceId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string? Key { get; set; }
|
||||||
|
|
||||||
[JsonProperty("language")]
|
[JsonProperty("language")]
|
||||||
public string Language { get; set; }
|
public string? Language { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nickname")]
|
[JsonProperty("nickname")]
|
||||||
public string Nickname { get; set; }
|
public string? Nickname { get; set; }
|
||||||
|
|
||||||
[JsonProperty("region")]
|
[JsonProperty("region")]
|
||||||
public string Region { get; set; }
|
public string? Region { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Auth;
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
public class LoginViaDeviceResponse
|
public class LoginViaDeviceResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("accessToken")]
|
[JsonProperty("accessToken")]
|
||||||
public string AccessToken { get; set; }
|
public string? AccessToken { get; set; }
|
||||||
|
|
||||||
[JsonProperty("refreshToken")]
|
[JsonProperty("refreshToken")]
|
||||||
public string RefreshToken { get; set; }
|
public string? RefreshToken { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Auth;
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
public class RefreshAccessTokenRequest
|
public class RefreshAccessTokenRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("refreshToken")]
|
[JsonProperty("refreshToken")]
|
||||||
public string RefreshToken { get; set; }
|
public string? RefreshToken { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Auth;
|
namespace RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
public class RefreshAccessTokenResponse
|
public class RefreshAccessTokenResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("accessToken")]
|
[JsonProperty("accessToken")]
|
||||||
public string AccessToken { get; set; }
|
public string? AccessToken { get; set; }
|
||||||
|
|
||||||
[JsonProperty("refreshToken")]
|
[JsonProperty("refreshToken")]
|
||||||
public string RefreshToken { get; set; }
|
public string? RefreshToken { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class AddBattlePassXpRequest
|
public class AddBattlePassXpRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("source")]
|
[JsonProperty("source")]
|
||||||
public string Source { get; set; }
|
public string? Source { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
@@ -9,18 +7,18 @@ namespace RudderSdk.Core.Models.BattlePass;
|
|||||||
public class AddBattlePassXpResponse
|
public class AddBattlePassXpResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("level")]
|
[JsonProperty("level")]
|
||||||
public int Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
[JsonProperty("leveledUp")]
|
[JsonProperty("leveledUp")]
|
||||||
public bool LeveledUp { get; set; }
|
public bool? LeveledUp { get; set; }
|
||||||
|
|
||||||
[JsonProperty("maxLevel")]
|
[JsonProperty("maxLevel")]
|
||||||
public bool MaxLevel { get; set; }
|
public bool? MaxLevel { get; set; }
|
||||||
|
|
||||||
[JsonProperty("plan")]
|
[JsonProperty("plan")]
|
||||||
public ExecutionPlan Plan { get; set; }
|
public ExecutionPlan? Plan { get; set; }
|
||||||
|
|
||||||
[JsonProperty("xp")]
|
[JsonProperty("xp")]
|
||||||
public long Xp { get; set; }
|
public long? Xp { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
|
||||||
|
|
||||||
public class BattlePassReward
|
|
||||||
{
|
|
||||||
[JsonProperty("amount")]
|
|
||||||
public long Amount { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("currency")]
|
|
||||||
public string Currency { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("itemId")]
|
|
||||||
public string ItemId { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class ClaimBattlePassRewardRequest
|
public class ClaimBattlePassRewardRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("level")]
|
[JsonProperty("level")]
|
||||||
public int Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("track")]
|
[JsonProperty("track")]
|
||||||
public string Track { get; set; }
|
public string? Track { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class ClaimBattlePassRewardResponse
|
public class ClaimBattlePassRewardResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("alreadyClaimed")]
|
[JsonProperty("alreadyClaimed")]
|
||||||
public bool AlreadyClaimed { get; set; }
|
public bool? AlreadyClaimed { get; set; }
|
||||||
|
|
||||||
[JsonProperty("error")]
|
[JsonProperty("error")]
|
||||||
public string Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
[JsonProperty("granted")]
|
[JsonProperty("granted")]
|
||||||
public List<BattlePassReward> Granted { get; set; }
|
public List<Reward>? Granted { get; set; }
|
||||||
|
|
||||||
[JsonProperty("success")]
|
[JsonProperty("success")]
|
||||||
public bool Success { get; set; }
|
public bool? Success { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class ClaimedTier
|
public class ClaimedTier
|
||||||
{
|
{
|
||||||
[JsonProperty("level")]
|
[JsonProperty("level")]
|
||||||
public int Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
[JsonProperty("track")]
|
[JsonProperty("track")]
|
||||||
public string Track { get; set; }
|
public string? Track { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class GetBattlePassProgressRequest
|
public class GetBattlePassProgressRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
@@ -8,15 +7,15 @@ namespace RudderSdk.Core.Models.BattlePass;
|
|||||||
public class GetBattlePassProgressResponse
|
public class GetBattlePassProgressResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("claimedTiers")]
|
[JsonProperty("claimedTiers")]
|
||||||
public List<ClaimedTier> ClaimedTiers { get; set; }
|
public List<ClaimedTier>? ClaimedTiers { get; set; }
|
||||||
|
|
||||||
[JsonProperty("level")]
|
[JsonProperty("level")]
|
||||||
public int Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
[JsonProperty("premiumOwned")]
|
[JsonProperty("premiumOwned")]
|
||||||
public bool PremiumOwned { get; set; }
|
public bool? PremiumOwned { get; set; }
|
||||||
|
|
||||||
[JsonProperty("xp")]
|
[JsonProperty("xp")]
|
||||||
public long Xp { get; set; }
|
public long? Xp { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
|
|
||||||
public class PurchaseBattlePassPremiumRequest
|
public class PurchaseBattlePassPremiumRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("idempotencyKey")]
|
[JsonProperty("idempotencyKey")]
|
||||||
public string IdempotencyKey { get; set; }
|
public string? IdempotencyKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.BattlePass;
|
namespace RudderSdk.Core.Models.BattlePass;
|
||||||
@@ -9,12 +7,12 @@ namespace RudderSdk.Core.Models.BattlePass;
|
|||||||
public class PurchaseBattlePassPremiumResponse
|
public class PurchaseBattlePassPremiumResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("error")]
|
[JsonProperty("error")]
|
||||||
public string Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
[JsonProperty("plan")]
|
[JsonProperty("plan")]
|
||||||
public ExecutionPlan Plan { get; set; }
|
public ExecutionPlan? Plan { get; set; }
|
||||||
|
|
||||||
[JsonProperty("success")]
|
[JsonProperty("success")]
|
||||||
public bool Success { get; set; }
|
public bool? Success { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.4.0
|
||||||
|
|
||||||
|
- Generated DTOs live under `Models/` (`RudderSdk.Core.Models`). Wire fields
|
||||||
|
are nullable. `ListQuestsRequest` is gone; `Quests.ListAsync` POSTs with
|
||||||
|
no body. `BoundaryNode.WaitDeadline` is `DateTimeOffset?`.
|
||||||
|
- `LeaderboardSession.ClaimAsync` / `Claim` complete the leaderboard node
|
||||||
|
with handle `onClaim`. The server matches live rank to an authored place.
|
||||||
|
- `RewardClaimedAsync` / `RewardClaimed` are obsolete aliases and will be
|
||||||
|
removed in the next SDK version.
|
||||||
|
- `rank_not_eligible` on Claim leaves the session open (retry Claim or End);
|
||||||
|
it no longer fails the run.
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Catalog;
|
|
||||||
|
|
||||||
public class CatalogItem
|
|
||||||
{
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("properties")]
|
|
||||||
public JToken Properties { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("slug")]
|
|
||||||
public string Slug { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tags")]
|
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Catalog;
|
|
||||||
|
|
||||||
public class ListCatalogItemsResponse
|
|
||||||
{
|
|
||||||
[JsonProperty("items")]
|
|
||||||
public List<CatalogItem> Items { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models;
|
|
||||||
|
|
||||||
public class ErrorResponse
|
|
||||||
{
|
|
||||||
[JsonProperty("code")]
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("error")]
|
|
||||||
public string Error { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("requestId")]
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Inventory;
|
namespace RudderSdk.Core.Models.Inventory;
|
||||||
@@ -8,6 +7,6 @@ namespace RudderSdk.Core.Models.Inventory;
|
|||||||
public class GetInventoryResponse
|
public class GetInventoryResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<PlayerInventoryItem> Items { get; set; }
|
public List<PlayerInventoryItem>? Items { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Inventory;
|
namespace RudderSdk.Core.Models.Inventory;
|
||||||
|
|
||||||
public class PlayerInventoryItem
|
public class PlayerInventoryItem
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nameOverride")]
|
[JsonProperty("nameOverride")]
|
||||||
public string NameOverride { get; set; }
|
public string? NameOverride { get; set; }
|
||||||
|
|
||||||
[JsonProperty("propertiesOverride")]
|
[JsonProperty("propertiesOverride")]
|
||||||
public JToken PropertiesOverride { get; set; }
|
public JToken? PropertiesOverride { get; set; }
|
||||||
|
|
||||||
[JsonProperty("slug")]
|
[JsonProperty("slug")]
|
||||||
public string Slug { get; set; }
|
public string? Slug { get; set; }
|
||||||
|
|
||||||
[JsonProperty("updatedAt")]
|
[JsonProperty("updatedAt")]
|
||||||
public string UpdatedAt { get; set; }
|
public DateTimeOffset? UpdatedAt { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Leaderboards;
|
namespace RudderSdk.Core.Models.Leaderboards;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.Leaderboards;
|
|||||||
public class GetRankingResponse
|
public class GetRankingResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("entries")]
|
[JsonProperty("entries")]
|
||||||
public List<RankEntry> Entries { get; set; }
|
public List<RankEntry>? Entries { get; set; }
|
||||||
|
|
||||||
[JsonProperty("total")]
|
[JsonProperty("total")]
|
||||||
public long Total { get; set; }
|
public long? Total { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Leaderboards;
|
namespace RudderSdk.Core.Models.Leaderboards;
|
||||||
|
|
||||||
public class RankEntry
|
public class RankEntry
|
||||||
{
|
{
|
||||||
[JsonProperty("playerId")]
|
[JsonProperty("playerId")]
|
||||||
public string PlayerId { get; set; }
|
public string? PlayerId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("playerName")]
|
[JsonProperty("playerName")]
|
||||||
public string PlayerName { get; set; }
|
public string? PlayerName { get; set; }
|
||||||
|
|
||||||
[JsonProperty("rank")]
|
[JsonProperty("rank")]
|
||||||
public long Rank { get; set; }
|
public long? Rank { get; set; }
|
||||||
|
|
||||||
[JsonProperty("score")]
|
[JsonProperty("score")]
|
||||||
public double Score { get; set; }
|
public double? Score { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Leaderboards;
|
namespace RudderSdk.Core.Models.Leaderboards;
|
||||||
|
|
||||||
public class SubmitScoreRequest
|
public class SubmitScoreRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("score")]
|
[JsonProperty("score")]
|
||||||
public double Score { get; set; }
|
public double? Score { get; set; }
|
||||||
|
|
||||||
[JsonProperty("slug")]
|
[JsonProperty("slug")]
|
||||||
public string Slug { get; set; }
|
public string? Slug { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,30 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models;
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
public class BoundaryNode
|
public class BoundaryNode
|
||||||
{
|
{
|
||||||
[JsonProperty("callbackUrl")]
|
[JsonProperty("callbackUrl")]
|
||||||
public string CallbackUrl { get; set; }
|
public string? CallbackUrl { get; set; }
|
||||||
|
|
||||||
[JsonProperty("enforcement")]
|
[JsonProperty("enforcement")]
|
||||||
public string Enforcement { get; set; }
|
public string? Enforcement { get; set; }
|
||||||
|
|
||||||
[JsonProperty("enteredAt")]
|
[JsonProperty("enteredAt")]
|
||||||
public string EnteredAt { get; set; }
|
public DateTimeOffset? EnteredAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("sourceHandle")]
|
[JsonProperty("sourceHandle")]
|
||||||
public string SourceHandle { get; set; }
|
public string? SourceHandle { get; set; }
|
||||||
|
|
||||||
[JsonProperty("sourceNodeId")]
|
[JsonProperty("sourceNodeId")]
|
||||||
public string SourceNodeId { get; set; }
|
public string? SourceNodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("waitDeadline")]
|
[JsonProperty("waitDeadline")]
|
||||||
public string WaitDeadline { get; set; }
|
public DateTimeOffset? WaitDeadline { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
|
public class ErrorResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("code")]
|
||||||
|
public string? Code { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("error")]
|
||||||
|
public string? Error { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("index")]
|
||||||
|
public int? Index { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("playerId")]
|
||||||
|
public string? PlayerId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("requestId")]
|
||||||
|
public string? RequestId { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,30 +8,30 @@ namespace RudderSdk.Core.Models;
|
|||||||
public class ExecutionPlan
|
public class ExecutionPlan
|
||||||
{
|
{
|
||||||
[JsonProperty("boundaryNodes")]
|
[JsonProperty("boundaryNodes")]
|
||||||
public List<BoundaryNode> BoundaryNodes { get; set; }
|
public List<BoundaryNode>? BoundaryNodes { get; set; }
|
||||||
|
|
||||||
[JsonProperty("context")]
|
[JsonProperty("context")]
|
||||||
public JToken Context { get; set; }
|
public JToken? Context { get; set; }
|
||||||
|
|
||||||
[JsonProperty("edges")]
|
[JsonProperty("edges")]
|
||||||
public List<PlanEdge> Edges { get; set; }
|
public List<PlanEdge>? Edges { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodes")]
|
[JsonProperty("nodes")]
|
||||||
public List<ExecutionPlanNode> Nodes { get; set; }
|
public List<ExecutionPlanNode>? Nodes { get; set; }
|
||||||
|
|
||||||
[JsonProperty("planId")]
|
[JsonProperty("planId")]
|
||||||
public string PlanId { get; set; }
|
public string? PlanId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("startNodeId")]
|
[JsonProperty("startNodeId")]
|
||||||
public string StartNodeId { get; set; }
|
public string? StartNodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("userId")]
|
[JsonProperty("userId")]
|
||||||
public string UserId { get; set; }
|
public string? UserId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models;
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
public class ExecutionPlanNode
|
public class ExecutionPlanNode
|
||||||
{
|
{
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public JToken Data { get; set; }
|
public JToken? Data { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models;
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
public class PlanEdge
|
public class PlanEdge
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("source")]
|
[JsonProperty("source")]
|
||||||
public string Source { get; set; }
|
public string? Source { get; set; }
|
||||||
|
|
||||||
[JsonProperty("sourceHandle")]
|
[JsonProperty("sourceHandle")]
|
||||||
public string SourceHandle { get; set; }
|
public string? SourceHandle { get; set; }
|
||||||
|
|
||||||
[JsonProperty("target")]
|
[JsonProperty("target")]
|
||||||
public string Target { get; set; }
|
public string? Target { get; set; }
|
||||||
|
|
||||||
[JsonProperty("targetHandle")]
|
[JsonProperty("targetHandle")]
|
||||||
public string TargetHandle { get; set; }
|
public string? TargetHandle { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
|
public class Reward
|
||||||
|
{
|
||||||
|
[JsonProperty("amount")]
|
||||||
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("currency")]
|
||||||
|
public string? Currency { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("itemId")]
|
||||||
|
public string? ItemId { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
|
|
||||||
namespace RudderSdk.Core;
|
namespace RudderSdk.Core.Models;
|
||||||
|
|
||||||
public static class RudderErrorCodes
|
public static class RudderErrorCodes
|
||||||
{
|
{
|
||||||
+7
-8
@@ -1,28 +1,27 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Player;
|
namespace RudderSdk.Core.Models.Player;
|
||||||
|
|
||||||
public class Player
|
public class Player
|
||||||
{
|
{
|
||||||
[JsonProperty("createdAt")]
|
[JsonProperty("createdAt")]
|
||||||
public string CreatedAt { get; set; }
|
public DateTimeOffset? CreatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("language")]
|
[JsonProperty("language")]
|
||||||
public string Language { get; set; }
|
public string? Language { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nickname")]
|
[JsonProperty("nickname")]
|
||||||
public string Nickname { get; set; }
|
public string? Nickname { get; set; }
|
||||||
|
|
||||||
[JsonProperty("projectId")]
|
[JsonProperty("projectId")]
|
||||||
public string ProjectId { get; set; }
|
public string? ProjectId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("region")]
|
[JsonProperty("region")]
|
||||||
public string Region { get; set; }
|
public string? Region { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Player;
|
namespace RudderSdk.Core.Models.Player;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.Player;
|
|||||||
public class PlayerProfile
|
public class PlayerProfile
|
||||||
{
|
{
|
||||||
[JsonProperty("player")]
|
[JsonProperty("player")]
|
||||||
public Player Player { get; set; }
|
public Player? Player { get; set; }
|
||||||
|
|
||||||
[JsonProperty("wallets")]
|
[JsonProperty("wallets")]
|
||||||
public List<Wallet> Wallets { get; set; }
|
public List<Wallet>? Wallets { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Player;
|
namespace RudderSdk.Core.Models.Player;
|
||||||
|
|
||||||
public class Wallet
|
public class Wallet
|
||||||
{
|
{
|
||||||
[JsonProperty("balance")]
|
[JsonProperty("balance")]
|
||||||
public long Balance { get; set; }
|
public long? Balance { get; set; }
|
||||||
|
|
||||||
[JsonProperty("currency")]
|
[JsonProperty("currency")]
|
||||||
public string Currency { get; set; }
|
public string? Currency { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.ProjectStorage;
|
namespace RudderSdk.Core.Models.ProjectStorage;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.ProjectStorage;
|
|||||||
public class GetProjectStorageResponse
|
public class GetProjectStorageResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<ProjectStorageItem> Items { get; set; }
|
public List<ProjectStorageItem>? Items { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nextCursor")]
|
[JsonProperty("nextCursor")]
|
||||||
public string NextCursor { get; set; }
|
public string? NextCursor { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,36 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.ProjectStorage;
|
namespace RudderSdk.Core.Models.ProjectStorage;
|
||||||
|
|
||||||
public class ProjectStorageItem
|
public class ProjectStorageItem
|
||||||
{
|
{
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public string Data { get; set; }
|
public string? Data { get; set; }
|
||||||
|
|
||||||
[JsonProperty("expiresAt")]
|
[JsonProperty("expiresAt")]
|
||||||
public string ExpiresAt { get; set; }
|
public DateTimeOffset? ExpiresAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("readPermission")]
|
[JsonProperty("readPermission")]
|
||||||
public string ReadPermission { get; set; }
|
public string? ReadPermission { get; set; }
|
||||||
|
|
||||||
[JsonProperty("size")]
|
[JsonProperty("size")]
|
||||||
public long Size { get; set; }
|
public long? Size { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
[JsonProperty("updatedAt")]
|
[JsonProperty("updatedAt")]
|
||||||
public string UpdatedAt { get; set; }
|
public DateTimeOffset? UpdatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("version")]
|
[JsonProperty("version")]
|
||||||
public long Version { get; set; }
|
public long? Version { get; set; }
|
||||||
|
|
||||||
[JsonProperty("writePermission")]
|
[JsonProperty("writePermission")]
|
||||||
public string WritePermission { get; set; }
|
public string? WritePermission { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.ProjectStorage;
|
namespace RudderSdk.Core.Models.ProjectStorage;
|
||||||
|
|
||||||
public class ProjectStorageUpdateItem
|
public class ProjectStorageUpdateItem
|
||||||
{
|
{
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public string Data { get; set; }
|
public string? Data { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.ProjectStorage;
|
namespace RudderSdk.Core.Models.ProjectStorage;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.ProjectStorage;
|
|||||||
public class UpdateProjectStorageRequest
|
public class UpdateProjectStorageRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("idempotencyKey")]
|
[JsonProperty("idempotencyKey")]
|
||||||
public string IdempotencyKey { get; set; }
|
public string? IdempotencyKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<ProjectStorageUpdateItem> Items { get; set; }
|
public List<ProjectStorageUpdateItem>? Items { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
|
|
||||||
public class ClaimQuestRequest
|
public class ClaimQuestRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("questId")]
|
[JsonProperty("questId")]
|
||||||
public string QuestId { get; set; }
|
public string? QuestId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
|
|
||||||
public class ClaimQuestResponse
|
public class ClaimQuestResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("alreadyClaimed")]
|
[JsonProperty("alreadyClaimed")]
|
||||||
public bool AlreadyClaimed { get; set; }
|
public bool? AlreadyClaimed { get; set; }
|
||||||
|
|
||||||
[JsonProperty("error")]
|
[JsonProperty("error")]
|
||||||
public string Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
[JsonProperty("granted")]
|
[JsonProperty("granted")]
|
||||||
public List<QuestReward> Granted { get; set; }
|
public List<Reward>? Granted { get; set; }
|
||||||
|
|
||||||
[JsonProperty("success")]
|
[JsonProperty("success")]
|
||||||
public bool Success { get; set; }
|
public bool? Success { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
|
||||||
|
|
||||||
public class ListQuestsRequest
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
@@ -8,6 +7,6 @@ namespace RudderSdk.Core.Models.Quests;
|
|||||||
public class ListQuestsResponse
|
public class ListQuestsResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("quests")]
|
[JsonProperty("quests")]
|
||||||
public List<Quest> Quests { get; set; }
|
public List<Quest>? Quests { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -1,25 +1,25 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
|
|
||||||
public class Quest
|
public class Quest
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[JsonProperty("objectives")]
|
[JsonProperty("objectives")]
|
||||||
public List<QuestObjectiveProgress> Objectives { get; set; }
|
public List<QuestObjectiveProgress>? Objectives { get; set; }
|
||||||
|
|
||||||
[JsonProperty("rewards")]
|
[JsonProperty("rewards")]
|
||||||
public List<QuestReward> Rewards { get; set; }
|
public List<Reward>? Rewards { get; set; }
|
||||||
|
|
||||||
[JsonProperty("status")]
|
[JsonProperty("status")]
|
||||||
public string Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
|
|
||||||
public class QuestObjectiveProgress
|
public class QuestObjectiveProgress
|
||||||
{
|
{
|
||||||
[JsonProperty("completed")]
|
[JsonProperty("completed")]
|
||||||
public bool Completed { get; set; }
|
public bool? Completed { get; set; }
|
||||||
|
|
||||||
[JsonProperty("current")]
|
[JsonProperty("current")]
|
||||||
public long Current { get; set; }
|
public long? Current { get; set; }
|
||||||
|
|
||||||
[JsonProperty("metric")]
|
[JsonProperty("metric")]
|
||||||
public string Metric { get; set; }
|
public string? Metric { get; set; }
|
||||||
|
|
||||||
[JsonProperty("objectiveId")]
|
[JsonProperty("objectiveId")]
|
||||||
public string ObjectiveId { get; set; }
|
public string? ObjectiveId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("target")]
|
[JsonProperty("target")]
|
||||||
public long Target { get; set; }
|
public long? Target { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
|
||||||
|
|
||||||
public class QuestReward
|
|
||||||
{
|
|
||||||
[JsonProperty("amount")]
|
|
||||||
public long Amount { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("currency")]
|
|
||||||
public string Currency { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("itemId")]
|
|
||||||
public string ItemId { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
|
|
||||||
public class ReportQuestProgressRequest
|
public class ReportQuestProgressRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("metric")]
|
[JsonProperty("metric")]
|
||||||
public string Metric { get; set; }
|
public string? Metric { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Quests;
|
namespace RudderSdk.Core.Models.Quests;
|
||||||
@@ -8,6 +7,6 @@ namespace RudderSdk.Core.Models.Quests;
|
|||||||
public class ReportQuestProgressResponse
|
public class ReportQuestProgressResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("completedQuestIds")]
|
[JsonProperty("completedQuestIds")]
|
||||||
public List<string> CompletedQuestIds { get; set; }
|
public List<string>? CompletedQuestIds { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ stack.
|
|||||||
| `Auth` | `AuthService` | `LoginWithDeviceAsync`, `RefreshAsync`, `Logout`, `AuthStateChanged` |
|
| `Auth` | `AuthService` | `LoginWithDeviceAsync`, `RefreshAsync`, `Logout`, `AuthStateChanged` |
|
||||||
| `Player` | `PlayerService` | `GetProfileAsync` |
|
| `Player` | `PlayerService` | `GetProfileAsync` |
|
||||||
| `BattlePass` | `BattlePassService` | `GetProgressAsync`, `AddXpAsync`, `ClaimRewardAsync`, `PurchasePremiumAsync` |
|
| `BattlePass` | `BattlePassService` | `GetProgressAsync`, `AddXpAsync`, `ClaimRewardAsync`, `PurchasePremiumAsync` |
|
||||||
| `Quests` | `QuestsService` | `ListAsync`, `ClaimAsync` |
|
| `Quests` | `QuestsService` | `ListAsync`, `ClaimAsync`, `ReportProgressAsync` |
|
||||||
| `Stores` | `StoresService` | `ListAsync`, `GetAsync`, `PurchaseAsync` |
|
| `Stores` | `StoresService` | `ListAsync`, `GetAsync`, `PurchaseAsync` |
|
||||||
| `Inventory` | `InventoryService` | `GetAsync` |
|
| `Inventory` | `InventoryService` | `GetAsync` |
|
||||||
| `Leaderboards` | `LeaderboardsService` | `FindBySlug(slug)` → handle: `SubmitAsync`, `ListAsync` |
|
| `Leaderboards` | `LeaderboardsService` | `FindBySlug(slug)` → handle: `SubmitAsync`, `ListAsync` |
|
||||||
@@ -62,6 +62,30 @@ stack.
|
|||||||
| `Storage` | `StorageService` | `GetAsync`, `ListAllAsync`, `SaveAsync`, `DeleteAsync` |
|
| `Storage` | `StorageService` | `GetAsync`, `ListAllAsync`, `SaveAsync`, `DeleteAsync` |
|
||||||
| `Realtime` | `RealtimeService` | `ConnectAsync`, `DisconnectAsync` |
|
| `Realtime` | `RealtimeService` | `ConnectAsync`, `DisconnectAsync` |
|
||||||
|
|
||||||
|
## Quests
|
||||||
|
|
||||||
|
`client.Quests` covers the player's global quests — list with per-objective
|
||||||
|
progress, claim, and metric reports. These are distinct from scenario quest
|
||||||
|
nodes, which advance through `QuestSession` (`Scenario.OnQuest`).
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var quests = await client.Quests.ListAsync();
|
||||||
|
foreach (var quest in quests)
|
||||||
|
{
|
||||||
|
if (quest.Status == "completed")
|
||||||
|
await client.Quests.ClaimAsync(quest.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom metrics advance matching objectives server-side; the call returns
|
||||||
|
// the ids of quests completed by this report.
|
||||||
|
var completedIds = await client.Quests.ReportProgressAsync("kills", 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
Purchase metrics are reported automatically by store purchases;
|
||||||
|
`QuestMetrics.PurchaseOffer(offerId)` / `QuestMetrics.PurchaseItem(itemId)`
|
||||||
|
name the format (`purchase.offer:<offerId>`, `purchase.item:<itemId>`) so
|
||||||
|
quest configs and client code agree on it.
|
||||||
|
|
||||||
## Sessions
|
## Sessions
|
||||||
|
|
||||||
Every API call goes through the client's session pipeline: a 401 triggers a
|
Every API call goes through the client's session pipeline: a 401 triggers a
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.RemoteConfig;
|
namespace RudderSdk.Core.Models.RemoteConfig;
|
||||||
@@ -8,6 +7,6 @@ namespace RudderSdk.Core.Models.RemoteConfig;
|
|||||||
public class ListRemoteConfigsResponse
|
public class ListRemoteConfigsResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("configs")]
|
[JsonProperty("configs")]
|
||||||
public Dictionary<string, RemoteConfig> Configs { get; set; }
|
public Dictionary<string, RemoteConfig>? Configs { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,39 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.RemoteConfig;
|
namespace RudderSdk.Core.Models.RemoteConfig;
|
||||||
|
|
||||||
public class RemoteConfig
|
public class RemoteConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("active")]
|
[JsonProperty("active")]
|
||||||
public bool Active { get; set; }
|
public bool? Active { get; set; }
|
||||||
|
|
||||||
[JsonProperty("createdAt")]
|
[JsonProperty("createdAt")]
|
||||||
public string CreatedAt { get; set; }
|
public DateTimeOffset? CreatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("description")]
|
[JsonProperty("description")]
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[JsonProperty("environment")]
|
[JsonProperty("environment")]
|
||||||
public string Environment { get; set; }
|
public string? Environment { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string? Key { get; set; }
|
||||||
|
|
||||||
[JsonProperty("projectId")]
|
[JsonProperty("projectId")]
|
||||||
public string ProjectId { get; set; }
|
public string? ProjectId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("updatedAt")]
|
[JsonProperty("updatedAt")]
|
||||||
public string UpdatedAt { get; set; }
|
public DateTimeOffset? UpdatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("value")]
|
[JsonProperty("value")]
|
||||||
public string Value { get; set; }
|
public string? Value { get; set; }
|
||||||
|
|
||||||
[JsonProperty("valueType")]
|
[JsonProperty("valueType")]
|
||||||
public string ValueType { get; set; }
|
public string? ValueType { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
<AssemblyName>Rudder.Core</AssemblyName>
|
<AssemblyName>Rudder.Core</AssemblyName>
|
||||||
<RootNamespace>RudderSdk.Core</RootNamespace>
|
<RootNamespace>RudderSdk.Core</RootNamespace>
|
||||||
<PackageId>Rudder.Core</PackageId>
|
<PackageId>Rudder.Core</PackageId>
|
||||||
<Version>0.3.0</Version>
|
<Version>0.4.0</Version>
|
||||||
<Authors>Rudder</Authors>
|
<Authors>Rudder</Authors>
|
||||||
<Description>Rudder LiveOps client SDK for .NET: auth, player, stores, battle pass, quests, leaderboards, inventory, remote config, scenarios, storage and realtime.</Description>
|
<Description>Rudder LiveOps client SDK for .NET: auth, player, stores, battle pass, quests, leaderboards, inventory, remote config, scenarios, storage and realtime.</Description>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
|
|
||||||
public class GetScenarioRunRequest
|
public class GetScenarioRunRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
@@ -9,12 +7,12 @@ namespace RudderSdk.Core.Models.Scenarios;
|
|||||||
public class GetScenarioRunResponse
|
public class GetScenarioRunResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("plan")]
|
[JsonProperty("plan")]
|
||||||
public ExecutionPlan Plan { get; set; }
|
public ExecutionPlan? Plan { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("status")]
|
[JsonProperty("status")]
|
||||||
public string Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
|
|
||||||
public class HandleScenarioCallbackRequest
|
public class HandleScenarioCallbackRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("handle")]
|
[JsonProperty("handle")]
|
||||||
public string Handle { get; set; }
|
public string? Handle { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
@@ -9,6 +7,6 @@ namespace RudderSdk.Core.Models.Scenarios;
|
|||||||
public class HandleScenarioCallbackResponse
|
public class HandleScenarioCallbackResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("plan")]
|
[JsonProperty("plan")]
|
||||||
public ExecutionPlan Plan { get; set; }
|
public ExecutionPlan? Plan { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
|
|
||||||
public class TriggerScenarioRequest
|
public class TriggerScenarioRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("event")]
|
[JsonProperty("event")]
|
||||||
public string Event { get; set; }
|
public string? Event { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
@@ -9,6 +8,6 @@ namespace RudderSdk.Core.Models.Scenarios;
|
|||||||
public class TriggerScenarioResponse
|
public class TriggerScenarioResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("plans")]
|
[JsonProperty("plans")]
|
||||||
public List<ExecutionPlan> Plans { get; set; }
|
public List<ExecutionPlan>? Plans { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
|
|
||||||
public class UpdateScenarioCounterRequest
|
public class UpdateScenarioCounterRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("counterKey")]
|
[JsonProperty("counterKey")]
|
||||||
public string CounterKey { get; set; }
|
public string? CounterKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nodeId")]
|
[JsonProperty("nodeId")]
|
||||||
public string NodeId { get; set; }
|
public string? NodeId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("runId")]
|
[JsonProperty("runId")]
|
||||||
public string RunId { get; set; }
|
public string? RunId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RudderSdk.Core.Models;
|
using RudderSdk.Core.Models;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Scenarios;
|
namespace RudderSdk.Core.Models.Scenarios;
|
||||||
@@ -9,9 +7,9 @@ namespace RudderSdk.Core.Models.Scenarios;
|
|||||||
public class UpdateScenarioCounterResponse
|
public class UpdateScenarioCounterResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("completed")]
|
[JsonProperty("completed")]
|
||||||
public bool Completed { get; set; }
|
public bool? Completed { get; set; }
|
||||||
|
|
||||||
[JsonProperty("plan")]
|
[JsonProperty("plan")]
|
||||||
public ExecutionPlan Plan { get; set; }
|
public ExecutionPlan? Plan { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-1
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using RudderSdk.Core.Models.Auth;
|
using RudderSdk.Core.Models.Auth;
|
||||||
|
|
||||||
namespace RudderSdk.Core;
|
namespace RudderSdk.Core;
|
||||||
@@ -41,7 +42,39 @@ public sealed class AuthService
|
|||||||
DeviceId = _client.DeviceIdProvider.DeviceId,
|
DeviceId = _client.DeviceIdProvider.DeviceId,
|
||||||
Region = region,
|
Region = region,
|
||||||
Language = language,
|
Language = language,
|
||||||
Nickname = nickname!
|
Nickname = nickname
|
||||||
|
},
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (response == null || string.IsNullOrEmpty(response.AccessToken) || string.IsNullOrEmpty(response.RefreshToken))
|
||||||
|
throw new InvalidOperationException("The server returned an incomplete session.");
|
||||||
|
|
||||||
|
_client.TokenStore.SaveTokens(response.AccessToken, response.RefreshToken);
|
||||||
|
NotifySignedIn();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signs the player in through the project's custom authorization webhook.
|
||||||
|
/// The returned token pair is stored in the configured token store.
|
||||||
|
/// </summary>
|
||||||
|
public async Task<LoginViaCustomResponse> LoginWithCustomAsync(
|
||||||
|
JToken customData,
|
||||||
|
string region,
|
||||||
|
string language,
|
||||||
|
string? nickname = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var response = await _client.SendAsync<LoginViaCustomRequest, LoginViaCustomResponse>(
|
||||||
|
"POST",
|
||||||
|
"/sdk/v1/authorization/custom",
|
||||||
|
new LoginViaCustomRequest
|
||||||
|
{
|
||||||
|
Key = _client.ProjectKey,
|
||||||
|
CustomData = customData,
|
||||||
|
Region = region,
|
||||||
|
Language = language,
|
||||||
|
Nickname = nickname
|
||||||
},
|
},
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace RudderSdk.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builders for the quest metric strings known to the platform. Purchase
|
||||||
|
/// metrics are reported automatically by the shop purchase fan-out; any other
|
||||||
|
/// metric is a custom string reported via
|
||||||
|
/// <see cref="QuestsService.ReportProgressAsync"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class QuestMetrics
|
||||||
|
{
|
||||||
|
/// <summary>Metric for purchasing a store offer; auto-reported on purchase.</summary>
|
||||||
|
public static string PurchaseOffer(string offerId) => $"purchase.offer:{offerId}";
|
||||||
|
|
||||||
|
/// <summary>Metric for purchasing a catalog item; auto-reported on purchase.</summary>
|
||||||
|
public static string PurchaseItem(string itemId) => $"purchase.item:{itemId}";
|
||||||
|
}
|
||||||
@@ -18,10 +18,9 @@ public sealed class QuestsService
|
|||||||
/// <summary>Lists the player's quests with per-objective progress and rewards.</summary>
|
/// <summary>Lists the player's quests with per-objective progress and rewards.</summary>
|
||||||
public async Task<IReadOnlyList<Quest>> ListAsync(CancellationToken cancellationToken = default)
|
public async Task<IReadOnlyList<Quest>> ListAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var response = await _client.SendAsync<ListQuestsRequest, ListQuestsResponse>(
|
var response = await _client.SendAsync<ListQuestsResponse>(
|
||||||
"POST",
|
"POST",
|
||||||
"/sdk/v1/quests/list",
|
"/sdk/v1/quests/list",
|
||||||
new ListQuestsRequest(),
|
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return response?.Quests ?? new List<Quest>();
|
return response?.Quests ?? new List<Quest>();
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ public sealed partial class ScenarioService
|
|||||||
// The server reports objective completion; it no longer returns a plan from the
|
// The server reports objective completion; it no longer returns a plan from the
|
||||||
// counter endpoint. On completion, cross the node's onComplete handle (which
|
// counter endpoint. On completion, cross the node's onComplete handle (which
|
||||||
// advances the run) — idempotent if the consumer also completes the session.
|
// advances the run) — idempotent if the consumer also completes the session.
|
||||||
if (response != null && response.Completed)
|
if (response != null && response.Completed == true)
|
||||||
await CompleteNodeAsync(runId, nodeId, "onComplete", cancellationToken).ConfigureAwait(false);
|
await CompleteNodeAsync(runId, nodeId, "onComplete", cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ public sealed partial class ScenarioService
|
|||||||
// Prefer server-provided WaitDeadline from the plan boundary over local calculation.
|
// Prefer server-provided WaitDeadline from the plan boundary over local calculation.
|
||||||
// The server stamps WaitDeadline on server-enforced wait boundaries (see StampBoundaries).
|
// The server stamps WaitDeadline on server-enforced wait boundaries (see StampBoundaries).
|
||||||
var boundary = run.Plan.BoundaryNodes?.FirstOrDefault(
|
var boundary = run.Plan.BoundaryNodes?.FirstOrDefault(
|
||||||
b => b.SourceNodeId == state.NodeId && !string.IsNullOrEmpty(b.WaitDeadline)
|
b => b.SourceNodeId == state.NodeId && b.WaitDeadline.HasValue
|
||||||
);
|
);
|
||||||
if (boundary != null && DateTimeOffset.TryParse(boundary.WaitDeadline, null, DateTimeStyles.RoundtripKind, out var parsed))
|
if (boundary?.WaitDeadline is { } parsed)
|
||||||
{
|
{
|
||||||
state.WaitDeadlineUtc = parsed;
|
state.WaitDeadlineUtc = parsed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ public sealed partial class ScenarioService
|
|||||||
return ex is OperationCanceledException || ex is RudderNetworkException;
|
return ex is OperationCanceledException || ex is RudderNetworkException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsRankNotEligible(Exception ex)
|
||||||
|
{
|
||||||
|
return ex is RudderApiException api && api.Code == "rank_not_eligible";
|
||||||
|
}
|
||||||
|
|
||||||
private IReadOnlyList<PlanRun> StartPlans(IEnumerable<ExecutionPlan>? plans)
|
private IReadOnlyList<PlanRun> StartPlans(IEnumerable<ExecutionPlan>? plans)
|
||||||
{
|
{
|
||||||
var started = new List<PlanRun>();
|
var started = new List<PlanRun>();
|
||||||
@@ -181,6 +186,8 @@ public sealed partial class ScenarioService
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
if (IsRankNotEligible(ex))
|
||||||
|
throw;
|
||||||
FailRun(run, nodeId, ex);
|
FailRun(run, nodeId, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public sealed class BattlePassSession
|
|||||||
IdempotencyKey = Guid.NewGuid().ToString()
|
IdempotencyKey = Guid.NewGuid().ToString()
|
||||||
}, cancellationToken).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (response != null && response.Success)
|
if (response != null && response.Success == true)
|
||||||
await Context.CompleteAsync("onPremiumPurchase", cancellationToken).ConfigureAwait(false);
|
await Context.CompleteAsync("onPremiumPurchase", cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return response!;
|
return response!;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -23,9 +24,17 @@ public sealed class LeaderboardSession
|
|||||||
/// <summary>Advances the run through the onEnd handle (fire-and-forget).</summary>
|
/// <summary>Advances the run through the onEnd handle (fire-and-forget).</summary>
|
||||||
public void End() => Context.Complete("onEnd");
|
public void End() => Context.Complete("onEnd");
|
||||||
|
|
||||||
/// <summary>Advances the run through the onRewardClaimed handle.</summary>
|
/// <summary>Advances the run through the onClaim handle. The server matches live rank to a place.</summary>
|
||||||
public Task RewardClaimedAsync(CancellationToken cancellationToken = default) => Context.CompleteAsync("onRewardClaimed", cancellationToken);
|
public Task ClaimAsync(CancellationToken cancellationToken = default) => Context.CompleteAsync("onClaim", cancellationToken);
|
||||||
|
|
||||||
/// <summary>Advances the run through the onRewardClaimed handle (fire-and-forget).</summary>
|
/// <summary>Advances the run through the onClaim handle (fire-and-forget).</summary>
|
||||||
public void RewardClaimed() => Context.Complete("onRewardClaimed");
|
public void Claim() => Context.Complete("onClaim");
|
||||||
|
|
||||||
|
/// <summary>Advances the run through the onClaim handle.</summary>
|
||||||
|
[Obsolete("Use ClaimAsync. Removed in the next SDK version.")]
|
||||||
|
public Task RewardClaimedAsync(CancellationToken cancellationToken = default) => ClaimAsync(cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>Advances the run through the onClaim handle (fire-and-forget).</summary>
|
||||||
|
[Obsolete("Use Claim. Removed in the next SDK version.")]
|
||||||
|
public void RewardClaimed() => Claim();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Storage;
|
namespace RudderSdk.Core.Models.Storage;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.Storage;
|
|||||||
public class GetStorageResponse
|
public class GetStorageResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<StorageItem> Items { get; set; }
|
public List<StorageItem>? Items { get; set; }
|
||||||
|
|
||||||
[JsonProperty("nextCursor")]
|
[JsonProperty("nextCursor")]
|
||||||
public string NextCursor { get; set; }
|
public string? NextCursor { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Storage;
|
namespace RudderSdk.Core.Models.Storage;
|
||||||
|
|
||||||
public class StorageItem
|
public class StorageItem
|
||||||
{
|
{
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public string Data { get; set; }
|
public string? Data { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Storage;
|
namespace RudderSdk.Core.Models.Storage;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.Storage;
|
|||||||
public class UpdateStorageRequest
|
public class UpdateStorageRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("idempotencyKey")]
|
[JsonProperty("idempotencyKey")]
|
||||||
public string IdempotencyKey { get; set; }
|
public string? IdempotencyKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<StorageItem> Items { get; set; }
|
public List<StorageItem>? Items { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
@@ -8,9 +7,9 @@ namespace RudderSdk.Core.Models.Stores;
|
|||||||
public class ListStoresResponse
|
public class ListStoresResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("stores")]
|
[JsonProperty("stores")]
|
||||||
public List<Store> Stores { get; set; }
|
public List<Store>? Stores { get; set; }
|
||||||
|
|
||||||
[JsonProperty("total")]
|
[JsonProperty("total")]
|
||||||
public int Total { get; set; }
|
public int? Total { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -1,6 +1,6 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
@@ -8,24 +8,24 @@ namespace RudderSdk.Core.Models.Stores;
|
|||||||
public class Offer
|
public class Offer
|
||||||
{
|
{
|
||||||
[JsonProperty("contents")]
|
[JsonProperty("contents")]
|
||||||
public List<OfferContent> Contents { get; set; }
|
public List<OfferContent>? Contents { get; set; }
|
||||||
|
|
||||||
[JsonProperty("createdAt")]
|
[JsonProperty("createdAt")]
|
||||||
public string CreatedAt { get; set; }
|
public DateTimeOffset? CreatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("maxPurchases")]
|
[JsonProperty("maxPurchases")]
|
||||||
public int MaxPurchases { get; set; }
|
public int? MaxPurchases { get; set; }
|
||||||
|
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[JsonProperty("price")]
|
[JsonProperty("price")]
|
||||||
public OfferPrice Price { get; set; }
|
public OfferPrice? Price { get; set; }
|
||||||
|
|
||||||
[JsonProperty("updatedAt")]
|
[JsonProperty("updatedAt")]
|
||||||
public string UpdatedAt { get; set; }
|
public DateTimeOffset? UpdatedAt { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
|
|
||||||
public class OfferContent
|
public class OfferContent
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("itemId")]
|
[JsonProperty("itemId")]
|
||||||
public string ItemId { get; set; }
|
public string? ItemId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
|
|
||||||
public class OfferPrice
|
public class OfferPrice
|
||||||
{
|
{
|
||||||
[JsonProperty("amount")]
|
[JsonProperty("amount")]
|
||||||
public long Amount { get; set; }
|
public long? Amount { get; set; }
|
||||||
|
|
||||||
[JsonProperty("currency")]
|
[JsonProperty("currency")]
|
||||||
public string Currency { get; set; }
|
public string? Currency { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
|
|
||||||
public class PurchaseOfferRequest
|
public class PurchaseOfferRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("idempotencyKey")]
|
[JsonProperty("idempotencyKey")]
|
||||||
public string IdempotencyKey { get; set; }
|
public string? IdempotencyKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("offerId")]
|
[JsonProperty("offerId")]
|
||||||
public string OfferId { get; set; }
|
public string? OfferId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("storeSlug")]
|
[JsonProperty("storeSlug")]
|
||||||
public string StoreSlug { get; set; }
|
public string? StoreSlug { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
|
|
||||||
public class PurchaseOfferResponse
|
public class PurchaseOfferResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("error")]
|
[JsonProperty("error")]
|
||||||
public string Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
[JsonProperty("purchaseId")]
|
[JsonProperty("purchaseId")]
|
||||||
public string PurchaseId { get; set; }
|
public string? PurchaseId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("success")]
|
[JsonProperty("success")]
|
||||||
public bool Success { get; set; }
|
public bool? Success { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -1,6 +1,7 @@
|
|||||||
// Code generated by apigen. DO NOT EDIT.
|
// Code generated by apigen. DO NOT EDIT.
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RudderSdk.Core.Models.Stores;
|
namespace RudderSdk.Core.Models.Stores;
|
||||||
@@ -8,39 +9,39 @@ namespace RudderSdk.Core.Models.Stores;
|
|||||||
public class Store
|
public class Store
|
||||||
{
|
{
|
||||||
[JsonProperty("createdAt")]
|
[JsonProperty("createdAt")]
|
||||||
public string CreatedAt { get; set; }
|
public DateTimeOffset? CreatedAt { get; set; }
|
||||||
|
|
||||||
[JsonProperty("data")]
|
[JsonProperty("data")]
|
||||||
public JToken Data { get; set; }
|
public JToken? Data { get; set; }
|
||||||
|
|
||||||
[JsonProperty("description")]
|
[JsonProperty("description")]
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
[JsonProperty("environment")]
|
[JsonProperty("environment")]
|
||||||
public string Environment { get; set; }
|
public string? Environment { get; set; }
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
[JsonProperty("offers")]
|
[JsonProperty("offers")]
|
||||||
public List<Offer> Offers { get; set; }
|
public List<Offer>? Offers { get; set; }
|
||||||
|
|
||||||
[JsonProperty("projectId")]
|
[JsonProperty("projectId")]
|
||||||
public string ProjectId { get; set; }
|
public string? ProjectId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("scenarioId")]
|
[JsonProperty("scenarioId")]
|
||||||
public string ScenarioId { get; set; }
|
public string? ScenarioId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("slug")]
|
[JsonProperty("slug")]
|
||||||
public string Slug { get; set; }
|
public string? Slug { get; set; }
|
||||||
|
|
||||||
[JsonProperty("status")]
|
[JsonProperty("status")]
|
||||||
public string Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
[JsonProperty("updatedAt")]
|
[JsonProperty("updatedAt")]
|
||||||
public string UpdatedAt { get; set; }
|
public DateTimeOffset? UpdatedAt { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
name: rudder-csharp-sdk
|
||||||
|
description: Use when working with the Rudder C# SDK Rudder.Core (namespace RudderSdk.Core) — client init, transports, auth/session lifecycle, and the per-domain services (player, stores, inventory, battle pass, quests, leaderboards, remote config, scenarios, storage, realtime).
|
||||||
|
---
|
||||||
|
|
||||||
|
# Rudder C# SDK (Rudder.Core)
|
||||||
|
|
||||||
|
.NET client SDK for the Rudder LiveOps platform. NuGet package `Rudder.Core`,
|
||||||
|
namespace `RudderSdk.Core` (DTOs under `RudderSdk.Core.Models.*`). Targets
|
||||||
|
`netstandard2.1` (works in Unity, .NET, Xamarin). JSON: Newtonsoft.Json
|
||||||
|
(`JToken`/`JObject` appear in public models). Everything is `async` with an
|
||||||
|
optional `CancellationToken` as the last parameter.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
dotnet add package Rudder.Core
|
||||||
|
```
|
||||||
|
|
||||||
|
## Client init
|
||||||
|
|
||||||
|
Only `BaseUrl` and `ProjectKey` are required; the constructor throws
|
||||||
|
`ArgumentException` when either is missing. Production API:
|
||||||
|
`https://api.rudder.build`. The project key is issued in the dashboard
|
||||||
|
(https://app.rudder.build/).
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using RudderSdk.Core;
|
||||||
|
|
||||||
|
var client = new RudderClient(new RudderClientOptions
|
||||||
|
{
|
||||||
|
BaseUrl = "https://api.rudder.build",
|
||||||
|
ProjectKey = "your-project-key"
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Defaults injected when the option is null (see reference/client.md for the
|
||||||
|
full options surface and the abstraction interfaces):
|
||||||
|
|
||||||
|
- `Transport` → `HttpClientTransport` (10 s request timeout)
|
||||||
|
- `TokenStore` → `InMemoryTokenStore` (session lost on restart — plug a
|
||||||
|
durable `ITokenStore` for production)
|
||||||
|
- `DeviceIdProvider` → `GuidDeviceIdProvider` (new GUID per run — plug a
|
||||||
|
persistent `IDeviceIdProvider` for production)
|
||||||
|
|
||||||
|
`RealtimeUrl` + `RealtimeTransportFactory` are required only for
|
||||||
|
`client.Realtime`; there is no default websocket transport in Rudder.Core.
|
||||||
|
|
||||||
|
## Request pipeline (applies to every service)
|
||||||
|
|
||||||
|
- All calls go to `{BaseUrl}/sdk/v1/...` with the stored access token as a
|
||||||
|
`Bearer` header.
|
||||||
|
- A 401 triggers one single-flight token refresh
|
||||||
|
(`POST /sdk/v1/authorization/refresh`) and one transparent retry. If the
|
||||||
|
refresh fails, tokens are cleared and `Auth.AuthStateChanged` fires
|
||||||
|
`RudderAuthState.SignedOut` — the game must sign in again.
|
||||||
|
- Non-success statuses throw `RudderApiException` subclasses; network
|
||||||
|
failures throw `RudderNetworkException` (`StatusCode == 0`). See
|
||||||
|
reference/errors.md.
|
||||||
|
- `client.Update(deltaTime)` must be called every frame — it pumps the
|
||||||
|
scenario runtime (wait-node deadlines) and the realtime transport.
|
||||||
|
|
||||||
|
## Capability map
|
||||||
|
|
||||||
|
| Domain | Entry point | Reference |
|
||||||
|
|---|---|---|
|
||||||
|
| Client, options, transports, abstractions | `RudderClient`, `RudderClientOptions` | reference/client.md |
|
||||||
|
| Errors, exceptions, error codes | `RudderApiException`, `RudderErrorCodes` | reference/errors.md |
|
||||||
|
| Auth (device/custom login, refresh, logout) | `client.Auth` | reference/auth.md |
|
||||||
|
| Player profile + wallets | `client.Player` | reference/player.md |
|
||||||
|
| Remote config (cached typed reads) | `client.RemoteConfig` | reference/remote-config.md |
|
||||||
|
| Player key-value storage | `client.Storage` | reference/storage.md |
|
||||||
|
| Project (global) storage | `client.ProjectStorage` | reference/project-storage.md |
|
||||||
|
| Stores and offer purchases | `client.Stores` | reference/stores.md |
|
||||||
|
| Leaderboards | `client.Leaderboards.FindBySlug(slug)` | reference/leaderboards.md |
|
||||||
|
| Inventory | `client.Inventory` | reference/inventory.md |
|
||||||
|
| Battle pass | `client.BattlePass` (+ scenario session) | reference/battlepass.md |
|
||||||
|
| Quests (global) | `client.Quests` | reference/quests.md |
|
||||||
|
| Scenarios (event-driven plans, node sessions) | `client.Scenario` | reference/scenarios.md |
|
||||||
|
| Realtime websocket | `client.Realtime` | reference/realtime.md |
|
||||||
|
|
||||||
|
Important cross-cutting facts:
|
||||||
|
|
||||||
|
- Battle pass state is tied to a scenario battle-pass node: every
|
||||||
|
`BattlePassService` call carries `ScenarioId`/`NodeId` (mutations also
|
||||||
|
`RunId`). During a scenario run, `BattlePassSession` supplies them — prefer
|
||||||
|
the session API inside a run.
|
||||||
|
- Global quests (`client.Quests`) are distinct from scenario quest nodes
|
||||||
|
(`Scenario.OnQuest` → `QuestSession`).
|
||||||
|
- Mutations that take an idempotency key auto-generate a random GUID when the
|
||||||
|
key is omitted (`Stores.PurchaseAsync`, `ProjectStorage.SaveAsync`,
|
||||||
|
`BattlePass.PurchasePremiumAsync`). Pass a stable key to make retries safe.
|
||||||
|
- Generated DTOs (`// Code generated by apigen`) use nullable properties and
|
||||||
|
`JsonProperty` snake_case names; never edit them by hand.
|
||||||
|
|
||||||
|
## Relationship to the Unity package (rudder.sdk)
|
||||||
|
|
||||||
|
`rudder.sdk` (UPM, liveops-unity-sdk) wraps `Rudder.Core.dll` with Unity
|
||||||
|
adapters: `UnityWebRequest` transport, `PlayerPrefs` token store, a websocket
|
||||||
|
realtime transport, and a `Rudder` bootstrap component
|
||||||
|
(`RudderSdk.Unity` namespace). The domain services and models are the same
|
||||||
|
ones documented here — for Unity games, consume them through the package's
|
||||||
|
adapters instead of wiring `RudderClientOptions` by hand. Unity requires
|
||||||
|
`com.unity.nuget.newtonsoft-json` since Rudder.Core serializes with
|
||||||
|
Newtonsoft.Json.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Auth — `client.Auth` (`AuthService`)
|
||||||
|
|
||||||
|
Source: `Services/AuthService.cs`, `RudderClient.cs` (refresh pipeline),
|
||||||
|
`Auth/*.cs` (generated DTOs), `RudderAuthState.cs`.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public event Action<RudderAuthState>? AuthStateChanged;
|
||||||
|
|
||||||
|
public Task<LoginViaDeviceResponse> LoginWithDeviceAsync(
|
||||||
|
string region, string language, string? nickname = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
public Task<LoginViaCustomResponse> LoginWithCustomAsync(
|
||||||
|
JToken customData, string region, string language, string? nickname = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
public Task<bool> RefreshAsync(); // false = session could not be renewed (tokens cleared)
|
||||||
|
|
||||||
|
public void Logout(); // drops the stored session, fires SignedOut
|
||||||
|
```
|
||||||
|
|
||||||
|
`RudderAuthState`: `SignedIn`, `SignedOut`. The event fires after a
|
||||||
|
successful login and after logout or a failed token refresh.
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
- `POST /sdk/v1/authorization/device` — body `{key, deviceId, region,
|
||||||
|
language, nickname?}`; `key` is the project key, `deviceId` comes from
|
||||||
|
`IDeviceIdProvider`.
|
||||||
|
- `POST /sdk/v1/authorization/custom` — body `{key, customData, region,
|
||||||
|
language, nickname?}`; `customData` is an arbitrary `JToken` forwarded to
|
||||||
|
the project's custom authorization webhook.
|
||||||
|
- `POST /sdk/v1/authorization/refresh` — body `{refreshToken}`; used by the
|
||||||
|
automatic pipeline and `RefreshAsync`.
|
||||||
|
|
||||||
|
## Response models (both logins)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class LoginViaDeviceResponse / LoginViaCustomResponse
|
||||||
|
{
|
||||||
|
public string? AccessToken { get; set; } // "accessToken"
|
||||||
|
public string? RefreshToken { get; set; } // "refreshToken"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Behavior notes
|
||||||
|
|
||||||
|
- A successful login stores the token pair in the configured `ITokenStore`
|
||||||
|
and fires `SignedIn`.
|
||||||
|
- If the server returns an incomplete session (missing tokens), login throws
|
||||||
|
`InvalidOperationException`.
|
||||||
|
- Token refresh is automatic: any API call that gets a 401 triggers one
|
||||||
|
single-flight refresh (concurrent 401s share one request) and one
|
||||||
|
transparent retry. A failed refresh clears the tokens and fires
|
||||||
|
`SignedOut`; the original call then throws `RudderAuthException`.
|
||||||
|
- `RefreshAsync()` shares the same single-flight path.
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
# Battle pass — `client.BattlePass` (`BattlePassService`)
|
||||||
|
|
||||||
|
Source: `Services/BattlePassService.cs`,
|
||||||
|
`Services/Scenarios/Sessions/BattlePassSession.cs`,
|
||||||
|
`Services/Scenarios/Sessions/BattlePassLevelSession.cs`, `BattlePass/*.cs`
|
||||||
|
(generated DTOs).
|
||||||
|
|
||||||
|
Battle pass state is tied to a scenario battle-pass node, so every call
|
||||||
|
carries `ScenarioId`/`NodeId` (mutations also `RunId`). Inside a scenario run,
|
||||||
|
`Scenario.OnBattlePass` hands you a `BattlePassSession` that supplies these
|
||||||
|
ids — prefer it over calling the service directly.
|
||||||
|
|
||||||
|
## BattlePassService
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public const string TrackFree = "free";
|
||||||
|
public const string TrackPremium = "premium";
|
||||||
|
|
||||||
|
// POST /sdk/v1/battlepass/progress
|
||||||
|
public Task<GetBattlePassProgressResponse> GetProgressAsync(
|
||||||
|
string scenarioId, string nodeId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/battlepass/xp
|
||||||
|
public Task<AddBattlePassXpResponse> AddXpAsync(
|
||||||
|
AddBattlePassXpRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/battlepass/claim — idempotent server-side
|
||||||
|
public Task<ClaimBattlePassRewardResponse> ClaimRewardAsync(
|
||||||
|
ClaimBattlePassRewardRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/battlepass/premium — charges the wallet; a random
|
||||||
|
// IdempotencyKey is generated when request.IdempotencyKey is null
|
||||||
|
public Task<PurchaseBattlePassPremiumResponse> PurchasePremiumAsync(
|
||||||
|
PurchaseBattlePassPremiumRequest request, CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Request DTOs (`RudderSdk.Core.Models.BattlePass`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class GetBattlePassProgressRequest
|
||||||
|
{
|
||||||
|
public string? NodeId { get; set; } // "nodeId"
|
||||||
|
public string? ScenarioId { get; set; } // "scenarioId"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddBattlePassXpRequest
|
||||||
|
{
|
||||||
|
public long? Amount { get; set; } // "amount"
|
||||||
|
public string? NodeId { get; set; } // "nodeId"
|
||||||
|
public string? RunId { get; set; } // "runId"
|
||||||
|
public string? ScenarioId { get; set; } // "scenarioId"
|
||||||
|
public string? Source { get; set; } // "source"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClaimBattlePassRewardRequest
|
||||||
|
{
|
||||||
|
public int? Level { get; set; } // "level"
|
||||||
|
public string? NodeId { get; set; } // "nodeId"
|
||||||
|
public string? RunId { get; set; } // "runId"
|
||||||
|
public string? ScenarioId { get; set; } // "scenarioId"
|
||||||
|
public string? Track { get; set; } // "track" — TrackFree / TrackPremium
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PurchaseBattlePassPremiumRequest
|
||||||
|
{
|
||||||
|
public string? IdempotencyKey { get; set; } // "idempotencyKey"
|
||||||
|
public string? NodeId { get; set; } // "nodeId"
|
||||||
|
public string? RunId { get; set; } // "runId"
|
||||||
|
public string? ScenarioId { get; set; } // "scenarioId"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response DTOs
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class GetBattlePassProgressResponse
|
||||||
|
{
|
||||||
|
public List<ClaimedTier>? ClaimedTiers { get; set; } // "claimedTiers"
|
||||||
|
public int? Level { get; set; } // "level"
|
||||||
|
public bool? PremiumOwned { get; set; } // "premiumOwned"
|
||||||
|
public long? Xp { get; set; } // "xp"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClaimedTier { public int? Level { get; set; } public string? Track { get; set; } }
|
||||||
|
|
||||||
|
public class AddBattlePassXpResponse
|
||||||
|
{
|
||||||
|
public int? Level { get; set; } // "level"
|
||||||
|
public bool? LeveledUp { get; set; } // "leveledUp"
|
||||||
|
public bool? MaxLevel { get; set; } // "maxLevel"
|
||||||
|
public ExecutionPlan? Plan { get; set; } // "plan" — scenario continuation
|
||||||
|
public long? Xp { get; set; } // "xp"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClaimBattlePassRewardResponse
|
||||||
|
{
|
||||||
|
public bool? AlreadyClaimed { get; set; } // "alreadyClaimed"
|
||||||
|
public string? Error { get; set; } // "error"
|
||||||
|
public List<Reward>? Granted { get; set; } // "granted"
|
||||||
|
public bool? Success { get; set; } // "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PurchaseBattlePassPremiumResponse
|
||||||
|
{
|
||||||
|
public string? Error { get; set; } // "error"
|
||||||
|
public ExecutionPlan? Plan { get; set; } // "plan"
|
||||||
|
public bool? Success { get; set; } // "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Reward` (`RudderSdk.Core.Models`): `Amount` (long?), `Currency` (string?),
|
||||||
|
`ItemId` (string?). Responses carry business errors in `Error` — check
|
||||||
|
`Success`. Claim failures surface codes such as `RudderErrorCodes.LevelNotReached`.
|
||||||
|
|
||||||
|
## BattlePassSession (scenario node session)
|
||||||
|
|
||||||
|
Raised via `Scenario.OnBattlePass`. Bound to the node's scenario/node/run ids:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public ScenarioNodeContext Context { get; }
|
||||||
|
public string Id { get; } // node id
|
||||||
|
public T Get<T>(string key, T defaultValue = default!);
|
||||||
|
|
||||||
|
public Task<GetBattlePassProgressResponse> GetProgressAsync(CancellationToken ct = default);
|
||||||
|
public Task<AddBattlePassXpResponse> AddXpAsync(string source, long amount, CancellationToken ct = default);
|
||||||
|
public Task<ClaimBattlePassRewardResponse> ClaimRewardAsync(int level, string track, CancellationToken ct = default);
|
||||||
|
|
||||||
|
// Purchases premium, then crosses the onPremiumPurchase handle on success.
|
||||||
|
public Task<PurchaseBattlePassPremiumResponse> PurchasePremiumAsync(CancellationToken ct = default);
|
||||||
|
|
||||||
|
// Boundary crossings (async + fire-and-forget variants):
|
||||||
|
public Task LevelUpAsync(CancellationToken ct = default); public void LevelUp(); // onLevelUp
|
||||||
|
public Task MaxLevelAsync(CancellationToken ct = default); public void MaxLevel(); // onMaxLevel
|
||||||
|
public Task CompleteAsync(CancellationToken ct = default); public void Complete(); // onComplete
|
||||||
|
```
|
||||||
|
|
||||||
|
## BattlePassLevelSession (scenario battlepass_level node)
|
||||||
|
|
||||||
|
Raised via `Scenario.OnBattlePassLevel`; a single claimable tier:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public int Level { get; } // reads the "levelNumber" node data key
|
||||||
|
public Task ClaimAsync(CancellationToken ct = default); public void Claim();
|
||||||
|
```
|
||||||
|
|
||||||
|
`ClaimAsync` crosses `onComplete`; the server accepts it only once the player
|
||||||
|
has reached the node's configured level.
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# Client, options, transports, abstractions
|
||||||
|
|
||||||
|
Source: `RudderClient.cs`, `RudderClientOptions.cs`, `HttpClientTransport.cs`,
|
||||||
|
`InMemoryTokenStore.cs`, `GuidDeviceIdProvider.cs`, `Abstractions/*.cs`.
|
||||||
|
|
||||||
|
## RudderClient
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class RudderClient
|
||||||
|
{
|
||||||
|
public AuthService Auth { get; }
|
||||||
|
public PlayerService Player { get; }
|
||||||
|
public RemoteConfigService RemoteConfig { get; }
|
||||||
|
public StorageService Storage { get; }
|
||||||
|
public ProjectStorageService ProjectStorage { get; }
|
||||||
|
public StoresService Stores { get; }
|
||||||
|
public LeaderboardsService Leaderboards { get; }
|
||||||
|
public InventoryService Inventory { get; }
|
||||||
|
public BattlePassService BattlePass { get; }
|
||||||
|
public QuestsService Quests { get; }
|
||||||
|
public ScenarioService Scenario { get; }
|
||||||
|
public RealtimeService Realtime { get; }
|
||||||
|
|
||||||
|
public string ProjectKey { get; }
|
||||||
|
public string? RealtimeUrl { get; }
|
||||||
|
public IClock Clock { get; } // defaults to DateTimeOffset.UtcNow
|
||||||
|
|
||||||
|
public RudderClient(RudderClientOptions options);
|
||||||
|
public void Update(float deltaTime); // pumps Scenario + Realtime; call every frame
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Constructor throws `ArgumentException` when `BaseUrl` or `ProjectKey` is
|
||||||
|
missing. Every API call goes through the client: a 401 triggers one
|
||||||
|
single-flight refresh and one transparent retry (see errors.md).
|
||||||
|
|
||||||
|
## RudderClientOptions
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class RudderClientOptions
|
||||||
|
{
|
||||||
|
public string? BaseUrl { get; set; } // required
|
||||||
|
public string? RealtimeUrl { get; set; } // required only for Realtime
|
||||||
|
public string? ProjectKey { get; set; } // required
|
||||||
|
public IRudderTransport? Transport { get; set; } // default HttpClientTransport
|
||||||
|
public ITokenStore? TokenStore { get; set; } // default InMemoryTokenStore
|
||||||
|
public IDeviceIdProvider? DeviceIdProvider { get; set; }// default GuidDeviceIdProvider
|
||||||
|
public IRudderLogger? Logger { get; set; } // null = silent
|
||||||
|
public IClock? Clock { get; set; } // override in tests
|
||||||
|
public IPlanStateStore? PlanStateStore { get; set; } // scenario persistence between launches
|
||||||
|
public IPlanScheduler? Scheduler { get; set; } // optional delayed plan work
|
||||||
|
public IRealtimeTransportFactory? RealtimeTransportFactory { get; set; } // required only for Realtime
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Default implementations
|
||||||
|
|
||||||
|
- `HttpClientTransport(string baseUrl, HttpClient? httpClient = null)` —
|
||||||
|
`IRudderTransport` over `HttpClient`, Newtonsoft.Json bodies, Bearer header,
|
||||||
|
10 s default timeout. Maps 401/404/429 to dedicated exception subclasses,
|
||||||
|
other non-success to `RudderApiException`, connectivity/timeout to
|
||||||
|
`RudderNetworkException`.
|
||||||
|
- `InMemoryTokenStore` — tokens in memory only; sessions do not survive an
|
||||||
|
app restart.
|
||||||
|
- `GuidDeviceIdProvider` — `Guid.NewGuid().ToString("N")` per instance; every
|
||||||
|
run looks like a fresh device to the backend.
|
||||||
|
|
||||||
|
## Abstractions (namespace `RudderSdk.Core.Abstractions`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public interface IRudderTransport
|
||||||
|
{
|
||||||
|
Task<TResponse> SendAsync<TRequest, TResponse>(
|
||||||
|
string method, string path, TRequest? request,
|
||||||
|
string? accessToken, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITokenStore
|
||||||
|
{
|
||||||
|
string? GetAccessToken();
|
||||||
|
string? GetRefreshToken();
|
||||||
|
void SaveTokens(string accessToken, string refreshToken);
|
||||||
|
void Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDeviceIdProvider { string DeviceId { get; } }
|
||||||
|
|
||||||
|
public interface IRudderLogger { void Log(RudderLogLevel level, string message); }
|
||||||
|
public enum RudderLogLevel { Debug, Info, Warning, Error }
|
||||||
|
|
||||||
|
public interface IClock { DateTimeOffset UtcNow { get; } }
|
||||||
|
|
||||||
|
public interface IPlanStateStore { string? State { get; set; } } // serialized scenario-run blob
|
||||||
|
|
||||||
|
public interface IPlanScheduler
|
||||||
|
{
|
||||||
|
Task ScheduleAsync(TimeSpan delay, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IRealtimeTransport
|
||||||
|
{
|
||||||
|
event Action Closed;
|
||||||
|
event Action<ArraySegment<byte>> Received;
|
||||||
|
event Action<Exception> Error;
|
||||||
|
bool IsConnected { get; }
|
||||||
|
Task ConnectAsync(Uri uri, TimeSpan timeout, CancellationToken cancellationToken = default);
|
||||||
|
Task SendAsync(ArraySegment<byte> data, CancellationToken cancellationToken = default);
|
||||||
|
Task CloseAsync(CancellationToken cancellationToken = default);
|
||||||
|
void Update(float deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IRealtimeTransportFactory { IRealtimeTransport Create(); }
|
||||||
|
```
|
||||||
|
|
||||||
|
Production guidance from the sources: provide a durable `ITokenStore`
|
||||||
|
(player prefs, keychain) and a persistent `IDeviceIdProvider` (Unity uses
|
||||||
|
`SystemInfo.deviceUniqueIdentifier`).
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Errors, exceptions, error codes
|
||||||
|
|
||||||
|
Source: `Exceptions/*.cs`, `Models/RudderErrorCodes.cs`,
|
||||||
|
`Models/ErrorResponse.cs`, `HttpClientTransport.cs` (status mapping),
|
||||||
|
`Services/Scenarios/ScenarioService.Runtime.cs` (`TransientBoundaryException`).
|
||||||
|
|
||||||
|
## Exception hierarchy
|
||||||
|
|
||||||
|
All API failures derive from `RudderApiException`:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class RudderApiException : Exception
|
||||||
|
{
|
||||||
|
public int StatusCode { get; } // 0 when the request never reached the server
|
||||||
|
public string Code { get; } // machine-readable API error code, "" when absent
|
||||||
|
public string? RequestId { get; } // server-issued request id for support tickets
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Exception | When |
|
||||||
|
|---|---|
|
||||||
|
| `RudderAuthException` | HTTP 401 after the automatic refresh+retry also failed — session is over, sign in again |
|
||||||
|
| `RudderNotFoundException` | HTTP 404 |
|
||||||
|
| `RudderRateLimitException` | HTTP 429 — back off and retry later |
|
||||||
|
| `RudderApiException` (base) | any other non-success status |
|
||||||
|
| `RudderNetworkException` | DNS/connectivity failure or client-side timeout; `StatusCode == 0`; retrying is safe for idempotent operations |
|
||||||
|
|
||||||
|
The transport parses the error body as `ErrorResponse`:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ErrorResponse // RudderSdk.Core.Models
|
||||||
|
{
|
||||||
|
public string? Code { get; set; } // "code"
|
||||||
|
public string? Error { get; set; } // "error" — human-readable message
|
||||||
|
public int? Index { get; set; } // "index"
|
||||||
|
public string? PlayerId { get; set; } // "playerId"
|
||||||
|
public string? RequestId { get; set; } // "requestId"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Non-JSON error bodies fall back to the HTTP reason phrase.
|
||||||
|
|
||||||
|
## Error code constants
|
||||||
|
|
||||||
|
`RudderSdk.Core.Models.RudderErrorCodes` (generated; scenario/battle-pass/quest
|
||||||
|
domain codes):
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
EarlyCompletion = "early_completion"
|
||||||
|
Forbidden = "forbidden"
|
||||||
|
LevelNotReached = "level_not_reached"
|
||||||
|
NodeNotActive = "node_not_active"
|
||||||
|
ObjectivesIncomplete = "objectives_incomplete"
|
||||||
|
RunExpired = "run_expired"
|
||||||
|
RunNotActive = "run_not_active"
|
||||||
|
ScenarioNotActive = "scenario_not_active"
|
||||||
|
UnknownRun = "unknown_run"
|
||||||
|
```
|
||||||
|
|
||||||
|
Match against `RudderApiException.Code`.
|
||||||
|
|
||||||
|
## Scenario boundary errors
|
||||||
|
|
||||||
|
`TransientBoundaryException` (public sealed, wraps the transport error) is
|
||||||
|
used inside the scenario runtime for transient boundary-callback failures
|
||||||
|
(timeout / `RudderNetworkException`): the run is NOT advanced, the node stays
|
||||||
|
active and the handle stays pending for retry. A failed scenario counter
|
||||||
|
update never fails the run — it is logged via `IRudderLogger` and the node
|
||||||
|
stays active.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Inventory — `client.Inventory` (`InventoryService`)
|
||||||
|
|
||||||
|
Source: `Services/InventoryService.cs`, `Inventory/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// GET /sdk/v1/inventory — lists the items the player owns
|
||||||
|
public Task<IReadOnlyList<PlayerInventoryItem>> GetAsync(CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Inventory`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class PlayerInventoryItem
|
||||||
|
{
|
||||||
|
public long? Amount { get; set; } // "amount"
|
||||||
|
public string? NameOverride { get; set; } // "nameOverride"
|
||||||
|
public JToken? PropertiesOverride { get; set; } // "propertiesOverride"
|
||||||
|
public string? Slug { get; set; } // "slug"
|
||||||
|
public DateTimeOffset? UpdatedAt { get; set; } // "updatedAt"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetInventoryResponse
|
||||||
|
{
|
||||||
|
public List<PlayerInventoryItem>? Items { get; set; } // "items"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The inventory is read-only from the client; amounts change through store
|
||||||
|
purchases and scenario/quest/battle-pass rewards.
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# Leaderboards — `client.Leaderboards` (`LeaderboardsService` + `LeaderboardHandle`)
|
||||||
|
|
||||||
|
Source: `Services/LeaderboardsService.cs`, `Leaderboards/*.cs` (generated
|
||||||
|
DTOs).
|
||||||
|
|
||||||
|
## Usage pattern
|
||||||
|
|
||||||
|
Resolve a (cached) handle by slug, then work through the handle:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var board = client.Leaderboards.FindBySlug("weekly-race");
|
||||||
|
await board.SubmitAsync(1250.5);
|
||||||
|
var entries = await board.ListAsync(limit: 50);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Signatures
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class LeaderboardsService
|
||||||
|
{
|
||||||
|
public LeaderboardHandle FindBySlug(string slug); // cached per slug
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class LeaderboardHandle
|
||||||
|
{
|
||||||
|
public string Slug { get; }
|
||||||
|
public IReadOnlyList<RankEntry> Entries { get; } // entries from the last ListAsync call
|
||||||
|
|
||||||
|
// POST /sdk/v1/leaderboards/{slug}/submit-score — submits for the current player
|
||||||
|
public Task SubmitAsync(double score, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// GET /sdk/v1/leaderboards/{slug}/ranking?limit={limit} — also caches into Entries
|
||||||
|
public Task<IReadOnlyList<RankEntry>> ListAsync(int limit = 100, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`limit <= 0` is omitted from the query (server default applies).
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Leaderboards`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class RankEntry
|
||||||
|
{
|
||||||
|
public string? PlayerId { get; set; } // "playerId"
|
||||||
|
public string? PlayerName { get; set; } // "playerName"
|
||||||
|
public long? Rank { get; set; } // "rank"
|
||||||
|
public double? Score { get; set; } // "score"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetRankingResponse
|
||||||
|
{
|
||||||
|
public List<RankEntry>? Entries { get; set; } // "entries"
|
||||||
|
public long? Total { get; set; } // "total"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: the working tree contains an untracked `Services/LeaderboardHandle.cs`
|
||||||
|
with a stale, slightly different `LeaderboardHandle` (no `Entries` cache). The
|
||||||
|
committed definition in `Services/LeaderboardsService.cs` documented above is
|
||||||
|
authoritative.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# Player — `client.Player` (`PlayerService`)
|
||||||
|
|
||||||
|
Source: `Services/PlayerService.cs`, `Player/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public Task<PlayerProfile> GetProfileAsync(CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
`GET /sdk/v1/player/information` — returns the player profile with wallets.
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Player`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class PlayerProfile
|
||||||
|
{
|
||||||
|
public Player? Player { get; set; } // "player"
|
||||||
|
public List<Wallet>? Wallets { get; set; } // "wallets"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Player
|
||||||
|
{
|
||||||
|
public DateTimeOffset? CreatedAt { get; set; } // "createdAt"
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Language { get; set; } // "language"
|
||||||
|
public string? Nickname { get; set; } // "nickname"
|
||||||
|
public string? ProjectId { get; set; } // "projectId"
|
||||||
|
public string? Region { get; set; } // "region"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Wallet
|
||||||
|
{
|
||||||
|
public long? Balance { get; set; } // "balance"
|
||||||
|
public string? Currency { get; set; } // "currency"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Wallet balances change through store purchases and scenario/quest/battle-pass
|
||||||
|
rewards; there is no client-side wallet mutation API.
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Project storage — `client.ProjectStorage` (`ProjectStorageService`)
|
||||||
|
|
||||||
|
Source: `Services/ProjectStorageService.cs`, `ProjectStorage/*.cs` (generated
|
||||||
|
DTOs).
|
||||||
|
|
||||||
|
Global key-value storage shared across all players of the project. Read is
|
||||||
|
open to every signed-in player; server-side permissions
|
||||||
|
(`readPermission`/`writePermission`) govern access.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// GET /sdk/v1/project-storage?types={type}&limit={limit}&cursor={cursor}
|
||||||
|
public Task<GetProjectStorageResponse> GetAsync(
|
||||||
|
string? type = null, int limit = 100, string? cursor = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// Follows cursor pagination over all items.
|
||||||
|
public IAsyncEnumerable<ProjectStorageItem> ListAllAsync(
|
||||||
|
string? type = null, int limit = 100,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// PUT /sdk/v1/project-storage — upserts items. When idempotencyKey is null a
|
||||||
|
// random GUID is generated; pass a stable key to make retries safe.
|
||||||
|
public Task SaveAsync(
|
||||||
|
IEnumerable<ProjectStorageUpdateItem> items, string? idempotencyKey = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
There is no client-side delete for project storage.
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.ProjectStorage`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ProjectStorageItem
|
||||||
|
{
|
||||||
|
public string? Data { get; set; } // "data"
|
||||||
|
public DateTimeOffset? ExpiresAt { get; set; } // "expiresAt"
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? ReadPermission { get; set; } // "readPermission"
|
||||||
|
public long? Size { get; set; } // "size"
|
||||||
|
public string? Type { get; set; } // "type"
|
||||||
|
public DateTimeOffset? UpdatedAt { get; set; } // "updatedAt"
|
||||||
|
public long? Version { get; set; } // "version"
|
||||||
|
public string? WritePermission { get; set; } // "writePermission"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProjectStorageUpdateItem // write shape: only type + data
|
||||||
|
{
|
||||||
|
public string? Data { get; set; } // "data"
|
||||||
|
public string? Type { get; set; } // "type"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetProjectStorageResponse
|
||||||
|
{
|
||||||
|
public List<ProjectStorageItem>? Items { get; set; } // "items"
|
||||||
|
public string? NextCursor { get; set; } // "nextCursor"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# Quests — `client.Quests` (`QuestsService`)
|
||||||
|
|
||||||
|
Source: `Services/QuestsService.cs`, `Services/QuestMetrics.cs`,
|
||||||
|
`Quests/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
Global quests (list + claim + metric reports). Distinct from scenario quest
|
||||||
|
nodes, which advance through `QuestSession` (`Scenario.OnQuest`) — see
|
||||||
|
scenarios.md.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// POST /sdk/v1/quests/list
|
||||||
|
public Task<IReadOnlyList<Quest>> ListAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/quests/claim — claims a completed quest's rewards (idempotent server-side)
|
||||||
|
public Task<ClaimQuestResponse> ClaimAsync(string questId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/quests/progress — reports progress for a metric; returns the
|
||||||
|
// ids of quests completed by THIS report
|
||||||
|
public Task<IReadOnlyList<string>> ReportProgressAsync(
|
||||||
|
string metric, long amount, CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metric strings — `QuestMetrics`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public static class QuestMetrics
|
||||||
|
{
|
||||||
|
public static string PurchaseOffer(string offerId); // "purchase.offer:{offerId}"
|
||||||
|
public static string PurchaseItem(string itemId); // "purchase.item:{itemId}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Purchase metrics are auto-reported by the shop purchase fan-out; any other
|
||||||
|
metric is a custom string passed to `ReportProgressAsync`.
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Quests`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class Quest
|
||||||
|
{
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Name { get; set; } // "name"
|
||||||
|
public List<QuestObjectiveProgress>? Objectives { get; set; }// "objectives"
|
||||||
|
public List<Reward>? Rewards { get; set; } // "rewards"
|
||||||
|
public string? Status { get; set; } // "status"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QuestObjectiveProgress
|
||||||
|
{
|
||||||
|
public bool? Completed { get; set; } // "completed"
|
||||||
|
public long? Current { get; set; } // "current"
|
||||||
|
public string? Metric { get; set; } // "metric"
|
||||||
|
public string? ObjectiveId { get; set; } // "objectiveId"
|
||||||
|
public long? Target { get; set; } // "target"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClaimQuestResponse
|
||||||
|
{
|
||||||
|
public bool? AlreadyClaimed { get; set; } // "alreadyClaimed"
|
||||||
|
public string? Error { get; set; } // "error"
|
||||||
|
public List<Reward>? Granted { get; set; } // "granted"
|
||||||
|
public bool? Success { get; set; } // "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Reward` (`RudderSdk.Core.Models`): `Amount` (long?), `Currency` (string?),
|
||||||
|
`ItemId` (string?). Claim a quest when its status reads `"completed"`; failed
|
||||||
|
claims surface `Error` and codes such as
|
||||||
|
`RudderErrorCodes.ObjectivesIncomplete` / `EarlyCompletion`.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Realtime — `client.Realtime` (`RealtimeService` + `RealtimeSession`)
|
||||||
|
|
||||||
|
Source: `Services/RealtimeService.cs`, `Abstractions/IRealtimeTransport.cs`,
|
||||||
|
`Abstractions/IRealtimeTransportFactory.cs`.
|
||||||
|
|
||||||
|
Websocket channel. Requires `RudderClientOptions.RealtimeUrl` and
|
||||||
|
`RudderClientOptions.RealtimeTransportFactory` — Rudder.Core ships no default
|
||||||
|
websocket transport (the Unity package `rudder.sdk` provides one). The current
|
||||||
|
access token authorizes the connection, so sign in first.
|
||||||
|
|
||||||
|
## RealtimeService
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public RealtimeSession? Session { get; } // null when not connected
|
||||||
|
public bool IsConnected { get; }
|
||||||
|
|
||||||
|
// Connects to the configured RealtimeUrl. Throws InvalidOperationException
|
||||||
|
// when RealtimeUrl is not configured.
|
||||||
|
public Task<RealtimeSession> ConnectAsync(TimeSpan? timeout = null, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// Connects to an explicit URL. Throws InvalidOperationException when
|
||||||
|
// RealtimeTransportFactory is missing or no access token is stored.
|
||||||
|
public Task<RealtimeSession> ConnectAsync(Uri uri, TimeSpan? timeout = null, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
public Task DisconnectAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
public void Update(float deltaTime); // pumps the transport; call every frame (client.Update does this)
|
||||||
|
```
|
||||||
|
|
||||||
|
Default connect timeout: 10 seconds.
|
||||||
|
|
||||||
|
## RealtimeSession
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public string AccessToken { get; } // token the connection was authorized with
|
||||||
|
public bool IsConnected { get; }
|
||||||
|
|
||||||
|
public event Action? Closed;
|
||||||
|
public event Action<Exception>? Error;
|
||||||
|
public event Action<ArraySegment<byte>>? MessageReceived;
|
||||||
|
|
||||||
|
public Task SendAsync(byte[] payload, CancellationToken cancellationToken = default);
|
||||||
|
public Task DisconnectAsync(CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
There is no message envelope or channel abstraction — payloads are raw bytes;
|
||||||
|
define the message shape with the server side of your project.
|
||||||
|
|
||||||
|
Note: the working tree contains an untracked `Services/RealtimeSession.cs`
|
||||||
|
with a stale `RealtimeSession` (no `AccessToken`). The committed definition in
|
||||||
|
`Services/RealtimeService.cs` documented above is authoritative.
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Remote config — `client.RemoteConfig` (`RemoteConfigService`)
|
||||||
|
|
||||||
|
Source: `Services/RemoteConfigService.cs`, `RemoteConfig/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
## Methods and properties
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public bool IsLoaded { get; } // true after first successful LoadAsync
|
||||||
|
public IReadOnlyDictionary<string, RemoteConfig> Configs { get; } // cache, keyed by config key
|
||||||
|
|
||||||
|
public Task<IReadOnlyDictionary<string, RemoteConfig>> LoadAsync(CancellationToken cancellationToken = default);
|
||||||
|
public Task<RemoteConfig> GetConfigAsync(string key, CancellationToken cancellationToken = default);
|
||||||
|
public T Get<T>(string key, T defaultValue = default!);
|
||||||
|
public Task<T> GetAsync<T>(string key, T defaultValue = default!, CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
Endpoints: `GET /sdk/v1/remote-configs` (list), `GET /sdk/v1/remote-configs/{key}`.
|
||||||
|
|
||||||
|
## Behavior notes
|
||||||
|
|
||||||
|
- `LoadAsync` fetches all configs and rebuilds the cache. A config whose raw
|
||||||
|
JSON has `"active": false` is excluded; a missing `active` flag means active.
|
||||||
|
- `Get<T>` reads from the cache only and returns `defaultValue` when the key
|
||||||
|
is missing or the value cannot be parsed (it never throws on parse errors).
|
||||||
|
- `GetAsync<T>` loads the cache on first use, then reads from it.
|
||||||
|
- `GetConfigAsync(key)` fetches one config straight from the server,
|
||||||
|
bypassing the cache.
|
||||||
|
- Typed parsing honors the config's `valueType`: `number`/`int`/`integer`/
|
||||||
|
`float`/`double` (invariant culture), `bool`/`boolean`, `json`/`object`
|
||||||
|
(deserialized via Newtonsoft.Json); anything else goes through
|
||||||
|
`Convert.ChangeType`. `string` values are returned as-is.
|
||||||
|
|
||||||
|
## Model (`RudderSdk.Core.Models.RemoteConfig`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class RemoteConfig
|
||||||
|
{
|
||||||
|
public bool? Active { get; set; } // "active"
|
||||||
|
public DateTimeOffset? CreatedAt { get; set; } // "createdAt"
|
||||||
|
public string? Description { get; set; } // "description"
|
||||||
|
public string? Environment { get; set; } // "environment"
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Key { get; set; } // "key"
|
||||||
|
public string? ProjectId { get; set; } // "projectId"
|
||||||
|
public DateTimeOffset? UpdatedAt { get; set; } // "updatedAt"
|
||||||
|
public string? Value { get; set; } // "value"
|
||||||
|
public string? ValueType { get; set; } // "valueType"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Scenario `remote_config_override` nodes apply patches directly into this
|
||||||
|
cache before `Scenario.OnConfigChanged` fires (see scenarios.md).
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
# Scenarios — `client.Scenario` (`ScenarioService`)
|
||||||
|
|
||||||
|
Source: `Services/ScenarioService.cs`, `Services/Scenarios/ScenarioService.{Dispatch,NodeTypes,Persistence,Runtime}.cs`,
|
||||||
|
`Services/Scenarios/Models/*.cs`, `Services/Scenarios/Sessions/*.cs`,
|
||||||
|
`Scenarios/*.cs` (generated DTOs), `Models/*.cs`.
|
||||||
|
|
||||||
|
Scenario runtime for server-issued execution plans. `TriggerAsync(eventName)`
|
||||||
|
starts plans; active nodes surface as typed sessions through the `On*` events
|
||||||
|
and are advanced by completing those sessions (which crosses server-validated
|
||||||
|
boundaries). Requires `Update(deltaTime)` every frame for wait-node deadlines.
|
||||||
|
|
||||||
|
## ScenarioService surface
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed partial class ScenarioService
|
||||||
|
{
|
||||||
|
// Node events
|
||||||
|
public event Action<NotificationSession>? OnNotification;
|
||||||
|
public event Action<StoreOfferSession>? OnStoreOffer;
|
||||||
|
public event Action<LeaderboardSession>? OnLeaderboard;
|
||||||
|
public event Action<ConfigChangedSession>? OnConfigChanged; // patches already applied
|
||||||
|
public event Action<WaitSession>? OnWait;
|
||||||
|
public event Action<QuestSession>? OnQuest;
|
||||||
|
public event Action<BattlePassSession>? OnBattlePass;
|
||||||
|
public event Action<BattlePassLevelSession>? OnBattlePassLevel;
|
||||||
|
|
||||||
|
// Run lifecycle events
|
||||||
|
public event Action<PlanRun>? OnScenarioCompleted; // run finished all nodes
|
||||||
|
public event Action<ScenarioFailedEvent>? OnScenarioFailed; // run died on unrecoverable error
|
||||||
|
|
||||||
|
public bool IsRunning { get; } // at least one run active
|
||||||
|
public string? CurrentNodeId { get; } // first active node id across runs
|
||||||
|
public IReadOnlyList<PlanRun> ActiveRuns { get; } // snapshots
|
||||||
|
|
||||||
|
// POST /sdk/v1/scenarios/trigger — body {event}; returns the runs this call started
|
||||||
|
public Task<IReadOnlyList<PlanRun>> TriggerAsync(string eventName, CancellationToken ct = default);
|
||||||
|
|
||||||
|
// Restores persisted runs (needs RudderClientOptions.PlanStateStore),
|
||||||
|
// reconciles with the server, re-dispatches active nodes. Call once after login.
|
||||||
|
public Task RestoreAsync(CancellationToken ct = default);
|
||||||
|
|
||||||
|
public void Clear(); // drops all runs and the persisted state
|
||||||
|
|
||||||
|
public void Update(float deltaTime); // completes wait nodes past their deadline
|
||||||
|
|
||||||
|
// Completes the FIRST active node of the FIRST run with the given handle.
|
||||||
|
public Task RespondAsync(string handle, CancellationToken ct = default);
|
||||||
|
public void Respond(string handle); // fire-and-forget
|
||||||
|
|
||||||
|
// Adds progress to a counter of the FIRST active node of the FIRST run.
|
||||||
|
public Task UpdateProgressAsync(string counterKey, long amount, CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Prefer session methods over `RespondAsync`/`UpdateProgressAsync` — the
|
||||||
|
parameterless variants only address the first active node of the first run.
|
||||||
|
|
||||||
|
## Node types and session handles
|
||||||
|
|
||||||
|
| Node `type` | Event | Session completion handles |
|
||||||
|
|---|---|---|
|
||||||
|
| `notification` | `OnNotification` | `output` (`CompleteAsync`/`Complete`) |
|
||||||
|
| `store` | `OnStoreOffer` | `onPurchase`, `onDecline` (`Purchase*`/`Decline*`, one-shot via `IsResolved`) |
|
||||||
|
| `wait` | `OnWait` | auto-completes `onComplete` at `WaitSession.DeadlineUtc` |
|
||||||
|
| `remote_config_override` | `OnConfigChanged` | auto-completes `output` after applying patches to `RemoteConfig` |
|
||||||
|
| `quest` | `OnQuest` | `onComplete`, `onFail`; `AddProgressAsync(counterKey, amount)` feeds counters |
|
||||||
|
| `leaderboard` | `OnLeaderboard` | `onEnd` (`End*`), `onClaim` (`Claim*` / obsolete `RewardClaimed*`) |
|
||||||
|
| `battlepass` | `OnBattlePass` | `onLevelUp`, `onMaxLevel`, `onComplete`, `onPremiumPurchase` (see battlepass.md) |
|
||||||
|
| `battlepass_level` | `OnBattlePassLevel` | `onComplete` via `ClaimAsync` — server checks the configured level |
|
||||||
|
|
||||||
|
An unsupported node type fails the run (`OnScenarioFailed`) instead of
|
||||||
|
stalling. All sessions expose `Context` (`ScenarioNodeContext`), `Id` (node
|
||||||
|
id) and `Get<T>(key, defaultValue)` for reading node data.
|
||||||
|
|
||||||
|
## ScenarioNodeContext
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public PlanRun Run { get; }
|
||||||
|
public ExecutionPlanNode Node { get; }
|
||||||
|
public string RunId / PlanId / ScenarioId / NodeId / Type { get; }
|
||||||
|
public JObject Data { get; }
|
||||||
|
public T Get<T>(string key, T defaultValue = default!);
|
||||||
|
public T Get<T>(); // whole payload
|
||||||
|
public Dictionary<string, object> AsObjectDictionary();
|
||||||
|
```
|
||||||
|
|
||||||
|
## PlanRun and failure event
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class PlanRun
|
||||||
|
{
|
||||||
|
public string RunId { get; }
|
||||||
|
public string PlanId { get; }
|
||||||
|
public string ScenarioId { get; }
|
||||||
|
public string UserId { get; }
|
||||||
|
public IReadOnlyList<string> ActiveNodeIds { get; }
|
||||||
|
public ExecutionPlan Plan { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ScenarioFailedEvent
|
||||||
|
{
|
||||||
|
public PlanRun Run { get; }
|
||||||
|
public string NodeId { get; }
|
||||||
|
public Exception Exception { get; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ExecutionPlan (generated, `RudderSdk.Core.Models`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ExecutionPlan
|
||||||
|
{
|
||||||
|
public List<BoundaryNode>? BoundaryNodes { get; set; }
|
||||||
|
public JToken? Context { get; set; }
|
||||||
|
public List<PlanEdge>? Edges { get; set; }
|
||||||
|
public List<ExecutionPlanNode>? Nodes { get; set; }
|
||||||
|
public string? PlanId { get; set; }
|
||||||
|
public string? RunId { get; set; }
|
||||||
|
public string? ScenarioId { get; set; }
|
||||||
|
public string? StartNodeId { get; set; }
|
||||||
|
public string? UserId { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ExecutionPlanNode`: `Id`, `Type`, `Data` (`JToken`). `PlanEdge`: `Id`,
|
||||||
|
`Source`, `SourceHandle`, `Target`, `TargetHandle`. `BoundaryNode`:
|
||||||
|
`CallbackUrl`, `Enforcement`, `EnteredAt`, `NodeId`, `SourceHandle`,
|
||||||
|
`SourceNodeId`, `WaitDeadline`.
|
||||||
|
|
||||||
|
## Runtime semantics
|
||||||
|
|
||||||
|
- Boundaries: crossing a handle that has a server boundary calls
|
||||||
|
`POST /sdk/v1/scenarios/callback` first; the returned continuation plan
|
||||||
|
replaces/starts the run before the handle is marked complete. On failure the
|
||||||
|
runtime reconciles via `POST /sdk/v1/scenarios/run`; `unknown_run` /
|
||||||
|
`expired` statuses drop the run. Transient failures
|
||||||
|
(`TransientBoundaryException`: timeouts, `RudderNetworkException`) leave the
|
||||||
|
node active for retry; terminal errors fail the run. `rank_not_eligible` on
|
||||||
|
leaderboard Claim leaves the node active (retry Claim or End).
|
||||||
|
- Counter updates (`POST /sdk/v1/scenarios/counter`) never fail the run; when
|
||||||
|
the server reports the objective completed, the node crosses `onComplete`
|
||||||
|
automatically.
|
||||||
|
- Dedup/idempotency: a plan with an already-running `RunId` is not restarted;
|
||||||
|
completed (node, handle) pairs are not re-crossed.
|
||||||
|
- Wait deadlines prefer the server-stamped `BoundaryNode.WaitDeadline` over
|
||||||
|
locally computed `duration`+`unit` node data (`days`/`hours`/`minutes`/
|
||||||
|
`seconds` and abbreviations).
|
||||||
|
- Persistence: with `IPlanStateStore` configured, every state change is
|
||||||
|
serialized into `State`; call `RestoreAsync` once after startup/login.
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Player storage — `client.Storage` (`StorageService`)
|
||||||
|
|
||||||
|
Source: `Services/StorageService.cs`, `Storage/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
Player-scoped key-value storage. Items carry a `type` (the "key" dimension)
|
||||||
|
and a string `data` payload.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// GET /sdk/v1/storage?types={type}&limit={limit}&cursor={cursor}
|
||||||
|
public Task<GetStorageResponse> GetAsync(
|
||||||
|
string? type = null, int limit = 100, string? cursor = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// Follows cursor pagination over all items.
|
||||||
|
public IAsyncEnumerable<StorageItem> ListAllAsync(
|
||||||
|
string? type = null, int limit = 100,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// PUT /sdk/v1/storage — upserts items. NOTE: the generated request DTO has an
|
||||||
|
// IdempotencyKey field, but SaveAsync does not set it (sent as null).
|
||||||
|
public Task SaveAsync(IEnumerable<StorageItem> items, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// DELETE /sdk/v1/storage?type={type} — deletes ALL items of the given type.
|
||||||
|
public Task DeleteAsync(string type, CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Storage`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class StorageItem
|
||||||
|
{
|
||||||
|
public string? Data { get; set; } // "data"
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Type { get; set; } // "type"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetStorageResponse
|
||||||
|
{
|
||||||
|
public List<StorageItem>? Items { get; set; } // "items"
|
||||||
|
public string? NextCursor { get; set; } // "nextCursor"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateStorageRequest
|
||||||
|
{
|
||||||
|
public string? IdempotencyKey { get; set; } // "idempotencyKey"
|
||||||
|
public List<StorageItem>? Items { get; set; } // "items"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`limit <= 0` is omitted from the query (server default applies). `data` is an
|
||||||
|
opaque string — serialize JSON into it yourself.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Stores — `client.Stores` (`StoresService`)
|
||||||
|
|
||||||
|
Source: `Services/StoresService.cs`, `Stores/*.cs` (generated DTOs).
|
||||||
|
|
||||||
|
In-game stores with offers priced in wallet currencies. Purchasing charges the
|
||||||
|
player's wallet and grants the offer contents.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// GET /sdk/v1/stores
|
||||||
|
public Task<IReadOnlyList<Store>> ListAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// GET /sdk/v1/stores/{slug}
|
||||||
|
public Task<Store> GetAsync(string slug, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
// POST /sdk/v1/stores/{storeSlug}/offers/{offerId}/purchase
|
||||||
|
// When idempotencyKey is null a random GUID is generated; pass a stable key to
|
||||||
|
// make retries safe.
|
||||||
|
public Task<PurchaseOfferResponse> PurchaseAsync(
|
||||||
|
string storeSlug, string offerId, string? idempotencyKey = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Models (`RudderSdk.Core.Models.Stores`)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class Store
|
||||||
|
{
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Slug { get; set; } // "slug"
|
||||||
|
public string? Name { get; set; } // "name"
|
||||||
|
public string? Description { get; set; } // "description"
|
||||||
|
public string? Status { get; set; } // "status"
|
||||||
|
public string? Environment { get; set; } // "environment"
|
||||||
|
public string? ProjectId { get; set; } // "projectId"
|
||||||
|
public string? ScenarioId { get; set; } // "scenarioId"
|
||||||
|
public JToken? Data { get; set; } // "data" — free-form
|
||||||
|
public List<Offer>? Offers { get; set; } // "offers"
|
||||||
|
public DateTimeOffset? CreatedAt { get; set; } // "createdAt"
|
||||||
|
public DateTimeOffset? UpdatedAt { get; set; } // "updatedAt"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Offer
|
||||||
|
{
|
||||||
|
public string? Id { get; set; } // "id"
|
||||||
|
public string? Name { get; set; } // "name"
|
||||||
|
public OfferPrice? Price { get; set; } // "price"
|
||||||
|
public List<OfferContent>? Contents { get; set; }// "contents"
|
||||||
|
public int? MaxPurchases { get; set; } // "maxPurchases"
|
||||||
|
public DateTimeOffset? CreatedAt { get; set; } // "createdAt"
|
||||||
|
public DateTimeOffset? UpdatedAt { get; set; } // "updatedAt"
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OfferPrice { public long? Amount { get; set; } public string? Currency { get; set; } }
|
||||||
|
public class OfferContent { public long? Amount { get; set; } public string? ItemId { get; set; } }
|
||||||
|
|
||||||
|
public class PurchaseOfferResponse
|
||||||
|
{
|
||||||
|
public string? Error { get; set; } // "error"
|
||||||
|
public string? PurchaseId { get; set; } // "purchaseId"
|
||||||
|
public bool? Success { get; set; } // "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`PurchaseOfferResponse.Error` carries a business error string when
|
||||||
|
`Success` is false — check the flag instead of relying on exceptions alone.
|
||||||
|
Purchases also auto-report quest metrics (`purchase.offer:{offerId}`) — see
|
||||||
|
quests.md.
|
||||||
Reference in New Issue
Block a user