using Gs2.Unity.Util; using Gs2.Unity.Core; using System; using Cysharp.Threading.Tasks; using System.Linq; using Gs2.Unity.Gs2LoginReward.Model; using Gs2.Unity.Gs2Mission.Model; using UnityEngine; public sealed class AdventureDaily : MonoBehaviour { [SerializeField] private AdventureLogin login; private Gs2Domain Client => login.Gs2; private IGameSession Session => login == null ? null : login.Session; [SerializeField] private string missionGroup = "adventure"; [SerializeField] private string missionName = "clear3"; private bool ready; private bool busy; private Func pendingOperation; private bool destroyed; private Action unsubscribe; private string message = "Loading..."; private EzReceiveStatus loginStatus; private EzCounter counter; private EzComplete complete; private const string LoginNamespace = "adventure-login-reward"; private const string MissionNamespace = "adventure-mission"; private void OnGUI() { if (Session == null) return; GUILayout.BeginArea(new Rect(700, 20, 650, 850), GUI.skin.box); GUILayout.Label("Login rewards and missions"); GUILayout.Label(message); if (!ready) { GUILayout.EndArea(); return; } for (var day = 0; day < 3; day++) { var claimed = loginStatus != null && loginStatus.ReceivedSteps != null && day < loginStatus.ReceivedSteps.Count && loginStatus.ReceivedSteps[day]; GUILayout.Label("Day " + (day + 1) + ": " + (day + 1) * 10 + " coins / " + (claimed ? "Claimed" : "Not claimed")); } GUI.enabled = ready && !busy && pendingOperation == null; if (GUILayout.Button("Claim today's login reward")) RunWrite(ReceiveLogin).Forget(); var clears = counter?.Values?.FirstOrDefault(value => value.ResetType == "notReset")?.Value ?? 0; var received = complete?.ReceivedMissionTaskNames?.Contains(missionName) == true; GUILayout.Label("Total adventures completed: " + clears); var completed = complete?.CompletedMissionTaskNames?.Contains(missionName) == true; GUILayout.Label(received ? "Claimed" : completed ? "You can claim the 30-coin mission reward" : "Mission in progress"); GUI.enabled = !busy && pendingOperation == null && completed && !received; var mission = missionName; if (GUILayout.Button("Claim 30-coin mission reward")) RunWrite(id => ReceiveMission(mission, id)).Forget(); GUI.enabled = !busy && pendingOperation != null; if (GUILayout.Button("Retry the same operation")) RetryWrite().Forget(); GUI.enabled = true; GUILayout.EndArea(); } private void Start() => Subscribe().Forget(); private void OnDestroy() { destroyed = true; unsubscribe?.Invoke(); } private async UniTask Subscribe() { try { await UniTask.WaitUntil(() => Session != null, cancellationToken: this.GetCancellationTokenOnDestroy()); var login = Client.LoginReward.Namespace(LoginNamespace).Me(Session).ReceiveStatus("daily"); var loginId = await login.SubscribeWithInitialCallAsync(value => loginStatus = value); if (!KeepSubscription(() => login.Unsubscribe(loginId))) return; var count = Client.Mission.Namespace(MissionNamespace).Me(Session).Counter("clear"); var counterId = await count.SubscribeWithInitialCallAsync(value => counter = value); if (!KeepSubscription(() => count.Unsubscribe(counterId))) return; var mission = Client.Mission.Namespace(MissionNamespace).Me(Session).Complete(missionGroup); var completeId = await mission.SubscribeWithInitialCallAsync(value => complete = value); if (!KeepSubscription(() => mission.Unsubscribe(completeId))) return; ready = true; message = ""; } catch (OperationCanceledException) { } catch (Exception error) { message = "Could not load: " + error.GetType().Name; } } private bool KeepSubscription(Action stop) { if (destroyed) { stop(); return false; } unsubscribe += stop; return true; } private async UniTask ReceiveLogin(string requestId) { var transaction = await Client.LoginReward.Namespace(LoginNamespace).Me(Session).Bonus() .ReceiveAsync("daily", speculativeExecute: false, duplicationAvoider: requestId); if (transaction != null) await transaction.WaitAsync(all: true); } private async UniTask ReceiveMission(string mission, string requestId) { var transaction = await Client.Mission.Namespace(MissionNamespace).Me(Session).Complete(missionGroup) .ReceiveRewardsAsync(mission, speculativeExecute: false, duplicationAvoider: requestId); if (transaction != null) await transaction.WaitAsync(all: true); } private async UniTask RunWrite(Func operation) { if (busy || pendingOperation != null || Session == null) return; var requestId = Guid.NewGuid().ToString(); pendingOperation = () => operation(requestId); await RetryWrite(); } private async UniTask RetryWrite() { if (busy || pendingOperation == null) return; busy = true; message = "Processing..."; try { await pendingOperation(); pendingOperation = null; message = "Done"; } catch (Exception error) when ( error is Gs2.Core.Exception.BadRequestException || error is Gs2.Gs2Money2.Exception.InsufficientException || error is Gs2.Gs2Inventory.Exception.InsufficientException || error is Gs2.Gs2Stamina.Exception.InsufficientException) { pendingOperation = null; message = "Action failed: " + error.Message; } catch (Exception error) { message = "Check the connection and retry the same operation: " + error.GetType().Name; } finally { busy = false; } } }