diff --git a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs new file mode 100644 index 00000000..8b1288a7 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections; +using UnityEngine; +using BackEnd; + +namespace TON +{ + /// + /// 뒤끝 서버 인증(로그인/회원가입) 담당 클래스 + /// + public class BackendAuthManager + { + private const string PASSWORD = "O-xmP0-=rp&kCq^"; + private const string CUSTOM_ID_KEY = "BackendCustomID"; + private const int MAX_RETRY_COUNT = 1; + + private int signUpRetryCount = 0; + + // 로그인 상태 + public bool IsLoggedIn { get; private set; } + + // 인증 이벤트 델리게이트 + public delegate void AuthEvent(bool isSuccess, string message); + public event AuthEvent OnLoginComplete; + public event AuthEvent OnSignUpComplete; + + /// + /// 자동 로그인 시도 + /// + public void TryAutoLogin() + { + string customID = GetOrCreateCustomID(); + + Backend.BMember.CustomLogin(customID, PASSWORD, callback => + { + if (callback.IsSuccess()) + { + Debug.Log("자동 로그인 성공!"); + IsLoggedIn = true; + OnLoginComplete?.Invoke(true, "로그인 성공"); + } + else + { + Debug.Log("로그인 실패, 회원가입 시도: " + callback.GetMessage()); + signUpRetryCount = 0; + TryAutoSignUp(customID); + } + }); + } + + /// + /// 자동 회원가입 시도 + /// + private void TryAutoSignUp(string customID) + { + Backend.BMember.CustomSignUp(customID, PASSWORD, callback => + { + if (callback.IsSuccess()) + { + Debug.Log("자동 회원가입 성공!"); + IsLoggedIn = true; + OnSignUpComplete?.Invoke(true, "회원가입 성공"); + } + else + { + Debug.LogError("자동 회원가입 실패: " + callback.GetMessage()); + HandleSignUpError(); + } + }); + } + + /// + /// 커스텀 ID 생성 또는 가져오기 + /// + private string GetOrCreateCustomID(bool forceNew = false) + { + string savedID = PlayerPrefs.GetString(CUSTOM_ID_KEY, string.Empty); + + if (string.IsNullOrEmpty(savedID) || forceNew) + { + string deviceID = SystemInfo.deviceUniqueIdentifier; + string appID = Application.identifier; + savedID = $"{appID}_{deviceID}_{DateTime.Now.Ticks}"; + + PlayerPrefs.SetString(CUSTOM_ID_KEY, savedID); + PlayerPrefs.Save(); + } + + return savedID; + } + + /// + /// 닉네임 변경 + /// + public void ChangeNickname(string newNickname, Action callback) + { + if (string.IsNullOrEmpty(newNickname) || newNickname.Length < 2) + { + callback?.Invoke(false, "닉네임은 2자 이상이어야 합니다."); + return; + } + + Backend.BMember.UpdateNickname(newNickname, bro => + { + if (bro.IsSuccess()) + { + Debug.Log("닉네임 변경 성공: " + newNickname); + callback?.Invoke(true, "닉네임이 변경되었습니다."); + } + else + { + Debug.LogError("닉네임 변경 실패: " + bro.GetMessage()); + callback?.Invoke(false, "닉네임 변경 실패: " + bro.GetMessage()); + } + }); + } + + /// + /// 회원가입 오류 처리 + /// + private void HandleSignUpError() + { + if (signUpRetryCount < MAX_RETRY_COUNT) + { + signUpRetryCount++; + Debug.Log($"회원가입 재시도 중... ({signUpRetryCount}/{MAX_RETRY_COUNT})"); + + // 이벤트 호출로 외부에서 회원가입 재시도 처리하도록 함 + OnSignUpComplete?.Invoke(false, "재시도 중"); + + // 새 ID로 재시도 + string newCustomID = GetOrCreateCustomID(true); + TryAutoSignUp(newCustomID); + } + else + { + OnSignUpComplete?.Invoke(false, "최대 재시도 횟수 초과"); + } + } + + /// + /// 로그아웃 + /// + public void Logout() + { + Backend.BMember.Logout(); + IsLoggedIn = false; + } + } +} \ No newline at end of file diff --git a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs.meta new file mode 100644 index 00000000..a33cfffc --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendAuthManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a196c27378aac149847085bba5be075 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs new file mode 100644 index 00000000..94212e33 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs @@ -0,0 +1,53 @@ +using UnityEngine; +using BackEnd; + +namespace TON +{ + /// + /// 뒤끝 서버 초기화 및 연결 담당 클래스 + /// + public class BackendInitializer + { + // 초기화 성공 여부 + public bool IsInitialized { get; private set; } + + // 초기화 이벤트 델리게이트 + public delegate void InitializeEvent(bool isSuccess); + public event InitializeEvent OnInitialized; + + /// + /// 뒤끝 서버 초기화 + /// + public void Initialize() + { + var bro = Backend.Initialize(); + + if (bro.IsSuccess()) + { + Debug.Log("뒤끝 서버 초기화 성공: " + bro); + IsInitialized = true; + OnInitialized?.Invoke(true); + } + else + { + Debug.LogError("뒤끝 서버 초기화 실패: " + bro); + IsInitialized = false; + OnInitialized?.Invoke(false); + } + } + + /// + /// 서버 상태 확인 + /// + public bool CheckServerStatus() + { + var bro = Backend.Utils.GetServerStatus(); + if (bro.StatusCode == 2) + { + Debug.LogWarning("서버 점검 중입니다."); + return false; + } + return true; + } + } +} \ No newline at end of file diff --git a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs.meta new file mode 100644 index 00000000..f251c2ef --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendInitializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7b42633cce5a6d4a989b0a01d5b1e97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendManager.cs b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendManager.cs index 450d440e..4ad75974 100644 --- a/Gameton-06/Assets/Gameton/Scripts/Backend/BackendManager.cs +++ b/Gameton-06/Assets/Gameton/Scripts/Backend/BackendManager.cs @@ -1,8 +1,5 @@ -using System.Collections; -using System.Collections.Generic; +using System; using UnityEngine; - -// 뒤끝 SDK namespace 추가 using BackEnd; namespace TON @@ -12,158 +9,102 @@ namespace TON /// public class BackendManager : SingletonBase { - private string PASSWORD = "O-xmP0-=rp&kCq^"; + // 하위 매니저 인스턴스 + private BackendInitializer initializer; + private BackendAuthManager authManager; - private int signUpRetryCount = 0; // 로그인 재시도 횟수 - private const int MAX_RETRY_COUNT = 1; // 최대 재시도 횟수 + // 초기화 완료 여부 + public bool IsInitialized => initializer?.IsInitialized ?? false; + public bool IsLoggedIn => authManager?.IsLoggedIn ?? false; + + // 에러 발생 시 콜백 + public event Action OnErrorOccurred; public void Initalize() { - var bro = Backend.Initialize(); // 뒤끝 초기화 + // 각 매니저 초기화 + initializer = new BackendInitializer(); + authManager = new BackendAuthManager(); - // 뒤끝 초기화에 대한 응답값 - if (bro.IsSuccess()) + // 이벤트 등록 + initializer.OnInitialized += HandleInitializeResult; + authManager.OnLoginComplete += HandleLoginResult; + authManager.OnSignUpComplete += HandleSignUpResult; + + // 초기화 시작 + initializer.Initialize(); + } + + // 초기화 결과 처리 + private void HandleInitializeResult(bool isSuccess) + { + if (isSuccess) { - Debug.Log("초기화 성공 : " + bro); // 성공일 경우 statusCode 204 Success - HandleBackendCallback(); + // 서버 상태 확인 후 로그인 시도 + if (initializer.CheckServerStatus()) + { + authManager.TryAutoLogin(); + } + else + { + ShowErrorAndQuitGame("서버 점검 중입니다. 잠시 후 다시 시도해주세요."); + } } else { - Debug.LogError("초기화 실패 : " + bro); // 실패일 경우 statusCode 400대 에러 발생 - } - } - - private void HandleBackendCallback() - { - // 서버 초기화 완료 후 자동 로그인 시도 - TryAutoLogin(); - } - - private void TryAutoLogin() - { - // 저장된 계정 정보 확인 - string customID = GetOrCreateCustomID(); - - // 자동 로그인 시도 - Backend.BMember.CustomLogin(customID, PASSWORD, callback => - { - if (callback.IsSuccess()) - { - Debug.Log("자동 로그인 성공!"); - // 게임 시작 로직 - // Main.cs 에서 처리하고 있기 때문에 별도 로직 처리하지 않음음 - } - else - { - // 로그인 실패 시 자동 회원가입 시도 - signUpRetryCount = 0; // 회원가입 시도 전 카운트 초기화 - TryAutoSignUp(customID); - } - }); - } - - private void TryAutoSignUp(string customID) - { - Backend.BMember.CustomSignUp(customID, PASSWORD, callback => - { - if (callback.IsSuccess()) - { - Debug.Log("자동 회원가입 성공!"); - // 게임 시작 로직 - // Main.cs 에서 처리하고 있기 때문에 별도 로직 처리하지 않음음 - } - else - { - Debug.LogError("자동 회원가입 실패: " + callback.GetMessage()); - // 재시도 또는 오류 처리 - HandleSignUpError(); - } - }); - } - - private string GetOrCreateCustomID(bool forceNew = false) - { - // PlayerPrefs에서 저장된 ID 확인 - string savedID = PlayerPrefs.GetString("BackendCustomID", string.Empty); - - if (string.IsNullOrEmpty(savedID) || forceNew) - { - // 새 ID 생성 (디바이스 고유 ID 활용) - string deviceID = SystemInfo.deviceUniqueIdentifier; - string appID = Application.identifier; - savedID = $"{appID}_{deviceID}_{System.DateTime.Now.Ticks}"; - - // 생성된 ID 저장 - PlayerPrefs.SetString("BackendCustomID", savedID); - PlayerPrefs.Save(); - } - - return savedID; - } - - // 캐릭터 닉네임 생성 시 유저 데이터에 닉네임 변경 적용용 - // 닉네임 변경 메소드 - public void ChangeNickname(string newNickname, System.Action callback) - { - // 닉네임 형식 검증 - if (string.IsNullOrEmpty(newNickname) || newNickname.Length < 2) - { - callback?.Invoke(false, "닉네임은 2자 이상이어야 합니다."); - return; - } - - // 뒤끝 서버 닉네임 변경 요청 - Backend.BMember.UpdateNickname(newNickname, bro => - { - if (bro.IsSuccess()) - { - Debug.Log("닉네임 변경 성공: " + newNickname); - callback?.Invoke(true, "닉네임이 변경되었습니다."); - } - else - { - Debug.LogError("닉네임 변경 실패: " + bro.GetMessage()); - callback?.Invoke(false, "닉네임 변경 실패: " + bro.GetMessage()); - } - }); - } - - - private void HandleSignUpError() - { - // 회원가입 실패 처리 - // 재시도 횟수 확인 - if (signUpRetryCount < MAX_RETRY_COUNT) - { - signUpRetryCount++; - Debug.Log($"회원가입 재시도 중... ({signUpRetryCount}/{MAX_RETRY_COUNT})"); - - // 약간의 딜레이 후 재시도 (네트워크 상태 개선 기회 제공) - Invoke(nameof(RetrySignUp), 2.0f); - } - else - { - // 최대 재시도 횟수 초과 - 게임 종료 ShowErrorAndQuitGame("서버 연결에 실패했습니다. 네트워크 상태를 확인하고 다시 시도해주세요."); } } - private void RetrySignUp() + // 로그인 결과 처리 + private void HandleLoginResult(bool isSuccess, string message) { - // 새로운 customID 생성 시도 (기존 ID에 문제가 있을 수 있음) - string newCustomID = GetOrCreateCustomID(true); - TryAutoSignUp(newCustomID); + if (isSuccess) + { + Debug.Log("로그인 성공!"); + // 게임 시작 로직은 Main.cs에서 처리 + } + else + { + Debug.LogWarning("로그인 실패: " + message); + // 로그인 실패는 회원가입 시도로 이어지므로 별도 처리 안함 + } + } + + // 회원가입 결과 처리 + private void HandleSignUpResult(bool isSuccess, string message) + { + if (isSuccess) + { + Debug.Log("회원가입 성공!"); + // 게임 시작 로직은 Main.cs에서 처리 + } + else if (message == "최대 재시도 횟수 초과") + { + ShowErrorAndQuitGame("서버 연결에 실패했습니다. 네트워크 상태를 확인하고 다시 시도해주세요."); + } + } + + // 닉네임 변경 함수 (외부에서 호출) + public void ChangeNickname(string newNickname, Action callback) + { + authManager.ChangeNickname(newNickname, callback); + } + + // 로그아웃 함수 (필요 시 추가) + public void Logout() + { + authManager.Logout(); } private void ShowErrorAndQuitGame(string errorMessage) { - // 에러 메시지 표시 (UI 구현 필요) Debug.LogError("게임 종료: " + errorMessage); + OnErrorOccurred?.Invoke(errorMessage); // 팝업 UI 표시 후 게임 종료 로직 ShowErrorPopup(errorMessage, () => { - // 팝업 확인 후 게임 종료 #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else @@ -172,7 +113,7 @@ namespace TON }); } - private void ShowErrorPopup(string message, System.Action onConfirm) + private void ShowErrorPopup(string message, Action onConfirm) { // TODO: 에러 팝업 UI 구현 // ErrorPopupManager.Instance.ShowPopup(message, onConfirm); @@ -181,6 +122,5 @@ namespace TON Debug.LogError("에러 팝업: " + message); onConfirm?.Invoke(); // 바로 콜백 실행 (실제로는 사용자 확인 후 실행) } - } -} +} \ No newline at end of file