using System; using Cysharp.Threading.Tasks; using UnityEngine; public sealed class AdventurePlay : MonoBehaviour { [SerializeField] private AdventureLogin login; private AdventurePlayer player; private bool busy; private bool awaitingResult; private bool blocked; private string message = "Waiting for login"; private bool CanInteract => player?.Ready == true && !busy; private bool CanWrite => CanInteract && player.HasPlayerData && !blocked; private async UniTask BeginQuest(string questName) { var transaction = await player.Gs2.Quest.Namespace("adventure-quest").Me(player.Session) .StartAsync("main", questName, force: false, speculativeExecute: false); awaitingResult = true; if (transaction != null) await transaction.WaitAsync(all: true); } private async UniTask CompleteQuest() { var transaction = await player.Gs2.Quest.Namespace("adventure-quest").Me(player.Session) .Progress().EndAsync(isComplete: true, speculativeExecute: false); awaitingResult = true; if (transaction != null) await transaction.WaitAsync(all: true); } private void OnGUI() { if (login.Session == null) return; GUILayout.BeginArea(new Rect(20, 210, 650, 650), GUI.skin.box); GUILayout.Label(message); if (player?.Ready == true) { DrawStatus(); DrawQuestButtons(); } GUI.enabled = true; GUILayout.EndArea(); } private void DrawQuestButtons() { GUI.enabled = CanWrite && player.Progress == null; foreach (var quest in player.Quests) { GUILayout.Label(quest.Metadata + " (" + quest.Name + ")"); if (GUILayout.Button("Start: " + quest.Name)) RunWrite(() => BeginQuest(quest.Name)).Forget(); } GUI.enabled = CanWrite && player.Progress != null; if (GUILayout.Button("Complete")) RunWrite(CompleteQuest).Forget(); } private void DrawStatus() { GUILayout.Label(player.Wallet?.Summary != null ? "Coins: " + player.Wallet.Summary.Free : "Could not load the coin balance"); GUILayout.Label(player.Progress == null ? "Choose an adventure" : "Adventure in progress"); } private void Start() => Initialize().Forget(); private void OnDestroy() => player?.Dispose(); private async UniTask Initialize() { busy = true; try { await UniTask.WaitUntil(() => login.Session != null, cancellationToken: this.GetCancellationTokenOnDestroy()); message = "Loading..."; player = new AdventurePlayer(login.Gs2, login.Session); await player.Load(); message = ""; } catch (OperationCanceledException) { } catch (Exception error) { message = "Could not load: " + error.GetType().Name; } finally { busy = false; } } private async UniTask RunWrite(Func operation) { if (!CanWrite) return; busy = true; awaitingResult = false; try { blocked = true; await operation(); blocked = false; message = ""; } catch (Exception error) { message = WriteError(error); } finally { busy = false; } } private string WriteError(Exception error) { if (awaitingResult) { return "Cannot confirm the submitted operation's result: " + error.GetType().Name; } if (error is Gs2.Core.Exception.BadRequestException) { blocked = false; return "Action failed. Check the settings."; } return "Cannot confirm the result. New actions are paused: " + error.GetType().Name; } }