Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Assets/Talo Game Services/Talo/Runtime/APIs/BaseAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace TaloGameServices
public class BaseAPI
{
// automatically updated with a pre-commit hook
private const string ClientVersion = "0.51.0";
private const string ClientVersion = "0.52.0";

protected string baseUrl;

Expand Down
74 changes: 66 additions & 8 deletions Assets/Talo Game Services/Talo/Runtime/APIs/DebouncedAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,52 @@ public abstract class DebouncedAPI<TOperation> : BaseAPI where TOperation : Enum
{
private class DebouncedOperation
{
public float nextUpdateTime;
public bool hasPending;
public float windowEndTime;
public bool windowOpen;
public bool hasTrailingCallQueued;
public bool isExecuting;
}

private readonly Dictionary<TOperation, DebouncedOperation> operations = new();

protected DebouncedAPI(string service) : base(service) { }

private void OpenWindow(DebouncedOperation op)
{
op.windowOpen = true;
op.windowEndTime = Time.realtimeSinceStartup + Talo.Settings.debounceTimerSeconds;
}

protected void Debounce(TOperation operation)
{
if (!operations.ContainsKey(operation))
{
operations[operation] = new DebouncedOperation();
}

operations[operation].nextUpdateTime = Time.realtimeSinceStartup + Talo.Settings.debounceTimerSeconds;
operations[operation].hasPending = true;
var op = operations[operation];

if (!op.windowOpen && !op.isExecuting)
{
// leading call: fire immediately and open the debounce window
op.hasTrailingCallQueued = false;
op.isExecuting = true;
OpenWindow(op);

ExecuteDebouncedOperation(operation).ContinueWith((t) => {
op.isExecuting = false;
if (t.IsFaulted)
{
Debug.LogError(t.Exception);
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
// window open or request in-flight: queue a trailing call and extend the window
op.hasTrailingCallQueued = true;
OpenWindow(op);
}
}

public async Task ProcessPendingUpdates()
Expand All @@ -34,16 +63,45 @@ public async Task ProcessPendingUpdates()

foreach (var kvp in operations)
{
if (kvp.Value.hasPending && Time.realtimeSinceStartup >= kvp.Value.nextUpdateTime)
var op = kvp.Value;
var windowClosed = Time.realtimeSinceStartup >= op.windowEndTime;
if (windowClosed)
{
keysToProcess.Add(kvp.Key);
if (op.hasTrailingCallQueued)
{
if (!op.isExecuting)
{
// window closed with a trailing call pending: execute it
keysToProcess.Add(kvp.Key);
}
else
{
// leading call still in-flight: delay trailing until it completes
OpenWindow(op);
}
}
else if (op.windowOpen)
{
// window closed with no trailing call: reset for the next leading call
op.windowOpen = false;
}
}
}

foreach (var key in keysToProcess)
{
operations[key].hasPending = false;
await ExecuteDebouncedOperation(key);
var op = operations[key];
op.hasTrailingCallQueued = false;
op.isExecuting = true;
try
{
await ExecuteDebouncedOperation(key);
}
finally
{
op.isExecuting = false;
op.windowOpen = false;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class GetEntriesOptions
{
public int page = 0;
public int aliasId = -1;
public string playerId = "";
public bool includeArchived = false;
public string propKey = "";
public string propValue = "";
Expand All @@ -20,6 +21,7 @@ public string ToQueryString()
{
var query = new Dictionary<string, string> { ["page"] = page.ToString() };
if (aliasId != -1) query["aliasId"] = aliasId.ToString();
if (!string.IsNullOrEmpty(playerId)) query["playerId"] = playerId;
if (includeArchived) query["withDeleted"] = "1";
if (!string.IsNullOrEmpty(propKey)) query["propKey"] = propKey;
if (!string.IsNullOrEmpty(propValue)) query["propValue"] = propValue;
Expand All @@ -32,7 +34,7 @@ public string ToQueryString()

public class LeaderboardsAPI : BaseAPI
{
private LeaderboardEntriesManager _entriesManager = new();
private readonly LeaderboardEntriesManager _entriesManager = new();

public LeaderboardsAPI() : base("v1/leaderboards") { }

Expand Down Expand Up @@ -65,6 +67,7 @@ public async Task<LeaderboardEntriesResponse> GetEntries(string internalName, Ge
return res;
}

[Obsolete("Use GetEntries(string internalName, GetEntriesOptions options) with the aliasId or playerId option instead.")]
public async Task<LeaderboardEntriesResponse> GetEntriesForCurrentPlayer(string internalName, GetEntriesOptions options = null)
{
Talo.IdentityCheck();
Expand All @@ -86,7 +89,7 @@ public async Task<LeaderboardEntriesResponse> GetEntries(string internalName, in
});
}

[Obsolete("Use GetEntriesForCurrentPlayer(string internalName, GetEntriesOptions options) instead.")]
[Obsolete("Use GetEntries(string internalName, GetEntriesOptions options) with the aliasId or playerId option instead.")]
public async Task<LeaderboardEntriesResponse> GetEntriesForCurrentPlayer(string internalName, int page, bool includeArchived = false)
{
Talo.IdentityCheck();
Expand Down
15 changes: 14 additions & 1 deletion Assets/Talo Game Services/Talo/Runtime/APIs/PlayerAuthAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace TaloGameServices
{
public class PlayerAuthAPI : BaseAPI
{
private SessionManager _sessionManager = new();
private readonly SessionManager _sessionManager = new();

public SessionManager SessionManager => _sessionManager;

Expand Down Expand Up @@ -114,6 +114,19 @@ public async Task ChangeEmail(string currentPassword, string newEmail)
await Call(uri, "POST", content);
}

public async Task ChangeIdentifier(string currentPassword, string newIdentifier)
{
var uri = new Uri($"{baseUrl}/change_identifier");
string content = JsonUtility.ToJson(new PlayerAuthChangeIdentifierRequest {
currentPassword = currentPassword,
newIdentifier = newIdentifier
});
var json = await Call(uri, "POST", content);

var res = JsonUtility.FromJson<PlayerAuthChangeIdentifierResponse>(json);
_sessionManager.HandleIdentifierUpdated(res);
}

public async Task ForgotPassword(string email)
{
var uri = new Uri($"{baseUrl}/forgot_password");
Expand Down
13 changes: 3 additions & 10 deletions Assets/Talo Game Services/Talo/Runtime/APIs/PlayersAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum DebouncedOperation
public event Action OnIdentificationFailed;
public event Action OnIdentityCleared;

private readonly string offlineDataPath = Application.persistentDataPath + "/ta.bin";
public static readonly string offlineDataPath = Application.persistentDataPath + "/ta.bin";

public PlayersAPI() : base("v1/players")
{
Expand Down Expand Up @@ -83,7 +83,7 @@ public async Task<Player> Identify(string service, string identifier)

var res = JsonUtility.FromJson<PlayersIdentifyResponse>(json);
var alias = res.alias;
WriteOfflineAlias(alias);
alias.WriteOfflineAlias();
return await HandleIdentifySuccess(alias, res.socketToken);
}
catch
Expand Down Expand Up @@ -133,7 +133,7 @@ public async Task<Player> Update()

var res = JsonUtility.FromJson<PlayersUpdateResponse>(json);
Talo.CurrentPlayer = res.player;
WriteOfflineAlias(Talo.CurrentAlias);
Talo.CurrentAlias.WriteOfflineAlias();

return Talo.CurrentPlayer;
}
Expand Down Expand Up @@ -191,13 +191,6 @@ private async Task<Player> IdentifyOffline(string service, string identifier)
}
}

private void WriteOfflineAlias(PlayerAlias alias)
{
if (!Talo.Settings.cachePlayerOnIdentify) return;
var content = JsonUtility.ToJson(alias);
Talo.Crypto.WriteFileContent(offlineDataPath, content);
}

private PlayerAlias GetOfflineAlias()
{
if (!Talo.Settings.cachePlayerOnIdentify || !File.Exists(offlineDataPath)) return null;
Expand Down
15 changes: 14 additions & 1 deletion Assets/Talo Game Services/Talo/Runtime/Entities/PlayerAlias.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace TaloGameServices
using UnityEngine;

namespace TaloGameServices
{
[System.Serializable]
public class PlayerAlias
Expand All @@ -12,5 +14,16 @@ public bool MatchesIdentifyRequest(string service, string identifier)
{
return this.service == service && this.identifier == identifier;
}

public void WriteOfflineAlias()
{
if (!Talo.Settings.cachePlayerOnIdentify)
{
return;
}

var content = JsonUtility.ToJson(this);
Talo.Crypto.WriteFileContent(PlayersAPI.offlineDataPath, content);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TaloGameServices
{
[System.Serializable]
public class PlayerAuthChangeIdentifierRequest
{
public string currentPassword;
public string newIdentifier;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TaloGameServices
{
[System.Serializable]
public class PlayerAuthChangeIdentifierResponse
{
public PlayerAlias alias;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace TaloGameServices
{
public class LeaderboardEntriesManager
{
private Dictionary<string, List<LeaderboardEntry>> _currentEntries = new Dictionary<string, List<LeaderboardEntry>>();
private readonly Dictionary<string, List<LeaderboardEntry>> _currentEntries = new();

public List<LeaderboardEntry> GetEntries(string internalName)
{
Expand All @@ -16,7 +16,7 @@ public List<LeaderboardEntry> GetEntries(string internalName)
return _currentEntries[internalName];
}

public void UpsertEntry(string internalName, LeaderboardEntry entry, bool bumpPositions = false)
public void UpsertEntry(string internalName, LeaderboardEntry entryToUpsert, bool bumpPositions = false)
{
if (!_currentEntries.ContainsKey(internalName))
{
Expand All @@ -26,18 +26,23 @@ public void UpsertEntry(string internalName, LeaderboardEntry entry, bool bumpPo
var entries = _currentEntries[internalName];

// ensure there isn't an existing entry
entries.RemoveAll((e) => e.id == entry.id);
entries.RemoveAll((e) => e.id == entryToUpsert.id);

int insertPosition = FindInsertPosition(entries, entry);
entries.Insert(insertPosition, entry);
int insertPosition = FindInsertPosition(entries, entryToUpsert);
entries.Insert(insertPosition, entryToUpsert);

if (bumpPositions)
{
foreach (var e in entries)
// if we find a collision, bump subsequent entries down by 1
int collisionIndex = entries.FindIndex((e) => e.id != entryToUpsert.id && e.position == entryToUpsert.position);
if (collisionIndex != -1)
{
if (e.id != entry.id && e.position >= entry.position)
for (int i = collisionIndex; i < entries.Count; i++)
{
e.position += 1;
if (entries[i].id != entryToUpsert.id)
{
entries[i].position += 1;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public enum PlayerAuthErrorCode {
NEW_EMAIL_MATCHES_CURRENT_EMAIL,
PASSWORD_RESET_CODE_INVALID,
VERIFICATION_EMAIL_REQUIRED,
INVALID_EMAIL
INVALID_EMAIL,
NEW_IDENTIFIER_MATCHES_CURRENT_IDENTIFIER
}

public class PlayerAuthException : Exception
Expand Down
14 changes: 13 additions & 1 deletion Assets/Talo Game Services/Talo/Runtime/Utils/SessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ public void HandleSessionCreated(PlayerAuthSessionResponse res)
Talo.Socket.SetSocketToken(res.socketToken);
}

private void SetIdentifierPlayerPref()
{
PlayerPrefs.SetString("TaloSessionIdentifier", Talo.CurrentAlias.identifier);
}

private void SaveSession(string sessionToken)
{
PlayerPrefs.SetString("TaloSessionToken", sessionToken);
PlayerPrefs.SetString("TaloSessionIdentifier", Talo.CurrentAlias.identifier);
SetIdentifierPlayerPref();
}

public async Task ClearSession()
Expand All @@ -42,5 +47,12 @@ public bool CheckForSession()
{
return !string.IsNullOrEmpty(GetSessionToken());
}

public void HandleIdentifierUpdated(PlayerAuthChangeIdentifierResponse res)
{
Talo.CurrentAlias = res.alias;
Talo.CurrentAlias.WriteOfflineAlias();
SetIdentifierPlayerPref();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ MonoBehaviour:
m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0}
m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}
m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0}
m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0}
m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0}
m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0}
m_ICUDataAsset: {fileID: 0}
forceGammaRendering: 0
textSettings: {fileID: 0}
Loading