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 = "로그인 대기 중"; 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("시작: " + quest.Name)) RunWrite(() => BeginQuest(quest.Name)).Forget(); } GUI.enabled = CanWrite && player.Progress != null; if (GUILayout.Button("클리어")) RunWrite(CompleteQuest).Forget(); } private void DrawStatus() { GUILayout.Label(player.Wallet?.Summary != null ? "코인: " + player.Wallet.Summary.Free : "코인 잔액을 가져올 수 없습니다"); GUILayout.Label(player.Progress == null ? "모험을 선택하세요" : "모험 진행 중"); } 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 = "로딩 중"; player = new AdventurePlayer(login.Gs2, login.Session); await player.Load(); message = ""; } catch (OperationCanceledException) { } catch (Exception error) { message = "불러오지 못했습니다: " + 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 "전송한 작업의 결과를 확인할 수 없습니다: " + error.GetType().Name; } if (error is Gs2.Core.Exception.BadRequestException) { blocked = false; return "작업을 실행하지 못했습니다. 설정을 확인하세요"; } return "처리 결과를 확인할 수 없어 새 작업을 중지했습니다: " + error.GetType().Name; } }