using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Threading.Tasks; using Firebase; using Firebase.Auth; using Google; using System; using UnityEngine.Events; using System.Text; using Newtonsoft.Json; using Firebase.Database; using Firebase.Crashlytics; using Firebase.Extensions; public class AccountManager : MonoBehaviour { [System.Serializable] public class UploadData { public string Email; public int Level; public int UnlockDataCount; public long Gold; public long Heart; public long Key; public long BuyKeyCount; public bool IsRemoveADS; public int FreeHeartCount, FreeKeyCount; public long BuyShopAccumulatedMoney; } private string webClientId = "502279241127-qvp2rjlutn9kqkpkjnr75uedi5hfu2dj.apps.googleusercontent.com"; [SerializeField] private float networkTimeout = 10.0f; [HideInInspector] public UnityEvent OnAccountSignIn; [HideInInspector] public UnityEvent OnAccountSignOut; [HideInInspector] public UnityEvent OnUploadSaveData; [HideInInspector] public UnityEvent OnDownloadSaveData; [HideInInspector] public UnityEvent OnOverWriteSaveData; private FirebaseAuth auth = null; private FirebaseUser user = null; private GoogleSignInConfiguration configuration; private bool isLoginFail = false; public bool IsLoginFail { get { return isLoginFail; } } public bool IsUserLogin { get { return user != null; } } private Coroutine checkExistSaveDataCoroutine; private Coroutine uploadCoroutine; private Coroutine downloadCoroutine; private UploadData uploadData = new UploadData(); StringBuilder sb = new StringBuilder(); private GoogleSignInUser signInUser = new GoogleSignInUser(); private AuthResult signInUser_Email; private bool IsTest = false; private void Awake() { configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestIdToken = true, RequestEmail = true }; //Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(false); //Crashlytics.ReportUncaughtExceptionsAsFatal = false; Firebase.FirebaseApp.LogLevel = Firebase.LogLevel.Debug; Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); Crashlytics.ReportUncaughtExceptionsAsFatal = true; Firebase.Analytics.FirebaseAnalytics.SetUserProperty( Firebase.Analytics.FirebaseAnalytics.UserPropertySignUpMethod, "Google"); AutoSignIn(); } void OnDestroy() { auth.StateChanged -= AuthStateChanged; auth = null; } public void SignOut() { if (IsTest) { OnSignOut_Email(); } else { OnSignOut(); } } private void SignOutFromGoogle() { OnSignOut(); } private void SignOutFromEmail() { OnSignOut_Email(); } public bool IsHaveLoginInfo() { return user != null ? user.IsValid() : false; } public void AutoSignIn() { StartCoroutine(StartAutoSignIn()); } // checkExistSaveData == 서버에 세이브가 존재하는 지를 확인한다. public void SignInWithUploadSaveData(bool checkExistSaveData) { if (IsTest) { StartCoroutine(StartSignInWithUploadSaveData_Email(checkExistSaveData)); } else { StartCoroutine(StartSignInWithUploadSaveData(checkExistSaveData)); } } public void SignInWithDownloadSaveData() { if (IsTest) { StartCoroutine(StartSignInWithDownloadSaveData_Email()); } else { StartCoroutine(StartSignInWithDownloadSaveData()); } } public string GetUserEmail() { if(user != null) { return user.Email; } return String.Empty; } public string GetUserID() { if (user != null) { return user.UserId; } return String.Empty; } private IEnumerator StartAutoSignIn() { Debug.Log("AccountManager: StartSignIn"); if (auth == null) { Task task = InitializeFirebase(); if (task.IsCompleted == false) { yield return new WaitUntil(() => task.IsCompleted); } if (task.Result != DependencyStatus.Available) { yield break; } yield return StartCoroutine(ReloadUserData()); } if (user != null) { if(IsTest) { OnSignIn_Email(); } else { OnSignIn(); } } else { Debug.LogError("AccountManager: StartSignIn: user is null"); OnAccountSignIn?.Invoke(false); } } private Task InitializeFirebase() { Debug.Log("AccountManager: InitializeFirebase"); // CheckAndFixDependenciesAsync() == 구글 플레이 서비스 버전 요구사항 확인할 때 사용하는 함수 Task tsak = FirebaseApp.CheckAndFixDependenciesAsync(); tsak.ContinueWithOnMainThread(task => { sb.Clear(); if (task.IsCompleted) { if (task.Result == DependencyStatus.Available) { auth = FirebaseAuth.DefaultInstance; auth.StateChanged += AuthStateChanged; AuthStateChanged(this, null); } else { isLoginFail = true; sb.Append("AccountManager: Could not resolve all Firebase dependencies: ").Append(task.Result.ToString()); Debug.LogError(sb.ToString()); } } else { isLoginFail = true; sb.Append("AccountManager: Dependency check was not completed. Error : ").Append(task.Result.ToString()); Debug.LogError(sb.ToString()); } }); return tsak; } private void AuthStateChanged(object sender, System.EventArgs eventArgs) { Debug.Log("AccountManager: AuthStateChanged"); if (auth.CurrentUser != user) { bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null; if (!signedIn && user != null) { Debug.Log("AccountManager: AuthStateChanged: Signed out"); } user = auth.CurrentUser; if (signedIn) { Debug.Log("AccountManager: AuthStateChanged: Signed in"); } } } private IEnumerator ReloadUserData() { Debug.Log("AccountManager: ReloadUserData"); yield return new WaitForEndOfFrame(); // 정보 다시 가져오기 if (user != null) { var reloadUserTask = user.ReloadAsync(); yield return new WaitUntil(predicate: () => reloadUserTask.IsCompleted); } } private Task OnSignIn() { Debug.Log("AccountManager: Calling SignIn"); GoogleSignIn.Configuration = configuration; GoogleSignIn.Configuration.UseGameSignIn = false; GoogleSignIn.Configuration.RequestIdToken = true; GoogleSignIn.Configuration.RequestEmail = true; Task task = GoogleSignIn.DefaultInstance.SignIn(); if (task.IsCompleted == false) { task.ContinueWith(OnAuthenticationFinished); } else { OnAuthenticationFinished(task); } return task; } private Task OnCredential(Credential credential) { Debug.Log("AccountManager: OnCredential"); Task task = auth.SignInWithCredentialAsync(credential); if (task.IsCompleted == false) { task.ContinueWith(OnCredentialFinished); } else { OnCredentialFinished(task); } return task; } private void OnSignOut() { Debug.Log("AccountManager: Calling SignOut"); GoogleSignIn.DefaultInstance.SignOut(); auth.SignOut(); Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(false); Crashlytics.ReportUncaughtExceptionsAsFatal = false; isLoginFail = false; user = null; OnAccountSignOut?.Invoke(true); } internal void OnAuthenticationFinished(Task task) { Debug.Log("AccountManager: OnAuthenticationFinished"); sb.Clear(); if (task.IsFaulted) { using (IEnumerator enumerator = task.Exception.InnerExceptions.GetEnumerator()) { if (enumerator.MoveNext()) { GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current; sb.Append("AccountManager: Got Error: ").Append(error.Status).Append(" ").Append(error.Message); Debug.LogError(sb.ToString()); } else { sb.Append("AccountManager: Got Unexpected Exception?!?").Append(task.Exception); Debug.LogError(sb.ToString()); } } OnAccountSignIn?.Invoke(false); isLoginFail = true; } else if (task.IsCanceled) { Debug.LogError("AccountManager: OnAuthenticationFinished: Canceled"); OnAccountSignIn?.Invoke(false); isLoginFail = true; } } internal void OnCredentialFinished(Task task) { Debug.LogError("AccountManager: OnCredentialFinished"); sb.Clear(); if (task.IsCanceled) { Debug.LogError("AccountManager: OnCredentialFinished: Canceled"); OnAccountSignIn?.Invoke(false); isLoginFail = true; } else if (task.IsFaulted) { using (IEnumerator enumerator = task.Exception.InnerExceptions.GetEnumerator()) { if (enumerator.MoveNext()) { GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current; sb.Append("AccountManager: Got Error: ").Append(error.Status).Append(" ").Append(error.Message); Debug.LogError(sb.ToString()); } else { sb.Append("AccountManager: Got Unexpected Exception?!?").Append(task.Exception); Debug.LogError(sb.ToString()); } } OnAccountSignIn?.Invoke(false); isLoginFail = true; } } private System.Threading.Tasks.Task SignInWithGoogleOnFirebase(string idToken) { Debug.LogError("AccountManager: SignInWithGoogleOnFirebase"); Credential credential = GoogleAuthProvider.GetCredential(idToken, null); return auth.SignInAndRetrieveDataWithCredentialAsync(credential).ContinueWith(task => { AggregateException ex = task.Exception; if (ex != null) { if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0)) { sb.Clear(); sb.Append("\nError code = ").Append(inner.ErrorCode).Append(" Message = ").Append(inner.Message); Debug.LogError(sb.ToString()); } OnAccountSignIn?.Invoke(false); isLoginFail = true; } else { Debug.Log("AccountManager: Sign In Successful."); user = task.Result.User; OnAccountSignIn?.Invoke(true); isLoginFail = false; if (auth.CurrentUser != null) { Firebase.Analytics.FirebaseAnalytics.SetUserId(auth.CurrentUser.UserId); } } }); } private IEnumerator StartSignInWithUploadSaveData(bool checkExistSaveData) { if (user == null) { Task signInTask = OnSignIn(); if (signInTask.IsCompleted == false) { yield return new WaitUntil(() => signInTask.IsCompleted); } if (signInTask.IsCompletedSuccessfully == true) { signInUser = signInTask.Result; sb.Append("AccountManager: Welcome: ").Append(signInTask.Result.Email); Debug.Log(sb.ToString()); /*Credential credential = GoogleAuthProvider.GetCredential(signInTask.Result.IdToken, null); Task credentialTask = OnCredential(credential); if (credentialTask.IsCompleted == false) { yield return new WaitUntil(() => credentialTask.IsCompleted); } if (credentialTask.IsCompletedSuccessfully == true) { Debug.Log("AccountManager: Sign In Successful."); user = credentialTask.Result; OnAccountSignIn.Invoke(true); isLoginFail = false; Firebase.FirebaseApp.LogLevel = Firebase.LogLevel.Debug; Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); Crashlytics.ReportUncaughtExceptionsAsFatal = true; Firebase.Analytics.FirebaseAnalytics.SetUserProperty( Firebase.Analytics.FirebaseAnalytics.UserPropertySignUpMethod, "Google"); if (auth.CurrentUser != null) { Firebase.Analytics.FirebaseAnalytics.SetUserId(auth.CurrentUser.UserId); } }*/ System.Threading.Tasks.Task signInWithGoogleOnFirebaseTask = SignInWithGoogleOnFirebase(signInTask.Result.IdToken); if (signInWithGoogleOnFirebaseTask.IsCompleted == false) { yield return new WaitUntil(() => signInWithGoogleOnFirebaseTask.IsCompleted); } } } if (checkExistSaveData) { checkExistSaveDataCoroutine = StartCoroutine(CheckExistSaveData()); } else { uploadCoroutine = StartCoroutine(UploadSaveData()); } } private IEnumerator CheckExistSaveData() { DatabaseReference databaseReference = FirebaseDatabase.DefaultInstance.RootReference; if (databaseReference != null) { databaseReference.Child("users").Child(user.UserId).GetValueAsync().ContinueWith(task => { if (task.IsFaulted || task.IsCanceled) { Debug.Log("AccountManager: CheckExistSaveData: DownloadSaveData Not Vaild"); if (uploadCoroutine != null) { StopCoroutine(uploadCoroutine); uploadCoroutine = null; } uploadCoroutine = StartCoroutine(UploadSaveData()); } else { DataSnapshot dataSnapshot = task.Result; var jsonFile = dataSnapshot.GetRawJsonValue(); UploadData downloadData = JsonConvert.DeserializeObject(jsonFile); if (downloadData.UnlockDataCount > GameManager.DB.GetUnlockTargetIndex(true) || downloadData.Level > GameManager.DB.NormalGameLevel) { Debug.Log("AccountManager: CheckExistSaveData: OverWriteSave"); } else { Debug.Log("AccountManager: CheckExistSaveData: DownloadSaveData Success"); if(uploadCoroutine != null) { StopCoroutine(uploadCoroutine); uploadCoroutine = null; } uploadCoroutine = StartCoroutine(UploadSaveData()); } } if (checkExistSaveDataCoroutine != null) { StopCoroutine(checkExistSaveDataCoroutine); checkExistSaveDataCoroutine = null; } }); yield return new WaitForSeconds(networkTimeout); OnUploadSaveData?.Invoke(false); } } private IEnumerator UploadSaveData() { DatabaseReference databaseReference = FirebaseDatabase.DefaultInstance.RootReference; if (databaseReference != null && user != null) { uploadData.Email = user.Email; uploadData.UnlockDataCount = GameManager.DB.GetUnlockTargetIndex(true); uploadData.Gold = GameManager.DB.Gold; uploadData.Heart = GameManager.DB.Heart; uploadData.Key = GameManager.DB.Key; uploadData.BuyKeyCount = GameManager.DB.BuyKeyCount; uploadData.Level = GameManager.DB.NormalGameLevel; uploadData.FreeHeartCount = GameManager.DB.FreeHeartCount; uploadData.FreeKeyCount = GameManager.DB.FreeKeyCount; uploadData.IsRemoveADS = GameManager.DB.IsRemoveADS; uploadData.BuyShopAccumulatedMoney = GameManager.DB.BuyShopAccumulatedMoney; string json = JsonConvert.SerializeObject(uploadData); databaseReference.Child("users").Child(user.UserId).SetRawJsonValueAsync(json).ContinueWith(task => { if (task.IsCanceled || task.IsFaulted) { Debug.LogError("AccountManager: UploadSaveData: UploadSaveData Fail"); AggregateException ex = task.Exception; if (ex != null) { if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0)) { sb.Clear(); sb.Append("AccountManager: UploadSaveData: UploadSaveData Fail: ").Append(inner.ErrorCode).Append(" Message = ").Append(inner.Message); Debug.LogError(sb.ToString()); } } OnUploadSaveData?.Invoke(false); } else { Debug.Log("AccountManager: UploadSaveData: UploadSaveData Success"); OnUploadSaveData?.Invoke(true); } if (uploadCoroutine != null) { StopCoroutine(uploadCoroutine); uploadCoroutine = null; } }); yield return new WaitForSeconds(networkTimeout); OnUploadSaveData?.Invoke(false); } } private IEnumerator StartSignInWithDownloadSaveData() { #if UNITY_EDITOR yield return null; GameManager.DB.DonwloadUnlockDataCount(100); GameManager.DB.DonwloadGoldData(4000); GameManager.DB.DonwloadHeartData(6); GameManager.DB.DonwloadKeyData(5); GameManager.DB.DownloadLevel(2); GameManager.DB.DownloadIsRemoveADS(true); OnDownloadSaveData?.Invoke(true); #else if (user == null) { Task signInTask = OnSignIn(); if (signInTask.IsCompleted == false) { yield return new WaitUntil(() => signInTask.IsCompleted); } if (signInTask.IsCompletedSuccessfully == true) { signInUser = signInTask.Result; sb.Append("AccountManager: Welcome: ").Append(signInTask.Result.Email); Debug.Log(sb.ToString()); Task signInWithGoogleOnFirebaseTask = SignInWithGoogleOnFirebase(signInTask.Result.IdToken); if(signInWithGoogleOnFirebaseTask.IsCompleted == false) { yield return new WaitUntil(() => signInWithGoogleOnFirebaseTask.IsCompleted); } } } downloadCoroutine = StartCoroutine(DownloadSaveData()); #endif } private IEnumerator DownloadSaveData() { DatabaseReference databaseReference = FirebaseDatabase.DefaultInstance.RootReference; if (databaseReference != null) { databaseReference.Child("users").Child(user.UserId).GetValueAsync().ContinueWith(task => { if (task.IsCanceled || task.IsFaulted) { Debug.LogError("AccountManager: DownloadSaveData: DownloadSaveData Fail"); OnDownloadSaveData?.Invoke(false); } else { Debug.Log("AccountManager: DownloadSaveData: DownloadSaveData Success"); DataSnapshot dataSnapshot = task.Result; var jsonFile = dataSnapshot.GetRawJsonValue(); UploadData downloadData = JsonConvert.DeserializeObject(jsonFile); GameManager.DB.DonwloadUnlockDataCount(downloadData.UnlockDataCount); GameManager.DB.DonwloadGoldData(downloadData.Gold); GameManager.DB.DonwloadHeartData(downloadData.Heart); GameManager.DB.DonwloadKeyData(downloadData.Key); GameManager.DB.DonwloadBuyKeyCountData(downloadData.BuyKeyCount); GameManager.DB.DownloadLevel(downloadData.Level); GameManager.DB.DownloadIsRemoveADS(downloadData.IsRemoveADS); GameManager.DB.DownloadBuyShopAccumulatedMoney(downloadData.BuyShopAccumulatedMoney); OnDownloadSaveData?.Invoke(true); } if (downloadCoroutine != null) { StopCoroutine(downloadCoroutine); downloadCoroutine = null; } }); yield return new WaitForSeconds(networkTimeout); OnDownloadSaveData?.Invoke(false); } } private Task OnSignIn_Email() { Debug.Log("AccountManager: Calling SignIn"); Task task = auth.SignInWithEmailAndPasswordAsync("class.redsun00@gmail.com", "class00"); if (task.IsCompleted == false) { task.ContinueWith(OnAuthenticationFinished_Email); } else { OnAuthenticationFinished_Email(task); } return task; } internal void OnAuthenticationFinished_Email(Task task) { Debug.Log("AccountManager: OnAuthenticationFinished_Email"); sb.Clear(); if (task.IsCanceled) { Debug.LogError("AccountManager: OnAuthenticationFinished_Email: SignInWithEmailAndPasswordAsync was canceled."); } if (task.IsFaulted) { Debug.LogError("AccountManager: OnAuthenticationFinished_Email: SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception); } else { return; } OnAccountSignIn?.Invoke(false); isLoginFail = true; } private IEnumerator StartSignInWithUploadSaveData_Email(bool checkExistSaveData) { if (user == null) { Task signInTask = OnSignIn_Email(); if (signInTask.IsCompleted == false) { yield return new WaitUntil(() => signInTask.IsCompleted); } if (signInTask.IsCompletedSuccessfully == true) { user = signInTask.Result.User; OnAccountSignIn?.Invoke(true); isLoginFail = false; Debug.Log("AccountManager: Sign In Successful."); sb.Append("AccountManager: Welcome: ").Append(signInTask.Result.User.Email); Debug.Log(sb.ToString()); Firebase.FirebaseApp.LogLevel = Firebase.LogLevel.Debug; Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); Crashlytics.ReportUncaughtExceptionsAsFatal = true; Firebase.Analytics.FirebaseAnalytics.SetUserProperty( Firebase.Analytics.FirebaseAnalytics.UserPropertySignUpMethod, "Google"); if (auth.CurrentUser != null) { Firebase.Analytics.FirebaseAnalytics.SetUserId(auth.CurrentUser.UserId); } } else { yield break; } } if (checkExistSaveData) { checkExistSaveDataCoroutine = StartCoroutine(CheckExistSaveData()); } else { uploadCoroutine = StartCoroutine(UploadSaveData()); } } private IEnumerator StartSignInWithDownloadSaveData_Email() { #if UNITY_EDITOR yield return null; GameManager.DB.DonwloadUnlockDataCount(100); GameManager.DB.DonwloadGoldData(4000); GameManager.DB.DonwloadHeartData(6); GameManager.DB.DonwloadKeyData(5); GameManager.DB.DownloadLevel(2); GameManager.DB.DownloadIsRemoveADS(true); OnDownloadSaveData?.Invoke(true); #else if (user == null) { Task signInTask = OnSignIn_Email(); if (signInTask.IsCompleted == false) { yield return new WaitUntil(() => signInTask.IsCompleted); } if (signInTask.IsCompletedSuccessfully == true) { user = signInTask.Result.User; OnAccountSignIn?.Invoke(true); isLoginFail = false; Debug.Log("AccountManager: Sign In Successful."); sb.Append("AccountManager: Welcome: ").Append(signInTask.Result.User.Email); Debug.Log(sb.ToString()); Firebase.FirebaseApp.LogLevel = Firebase.LogLevel.Debug; Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); Crashlytics.ReportUncaughtExceptionsAsFatal = true; Firebase.Analytics.FirebaseAnalytics.SetUserProperty( Firebase.Analytics.FirebaseAnalytics.UserPropertySignUpMethod, "Google"); if (auth.CurrentUser != null) { Firebase.Analytics.FirebaseAnalytics.SetUserId(auth.CurrentUser.UserId); } } else { yield break; } } downloadCoroutine = StartCoroutine(DownloadSaveData()); #endif } private void OnSignOut_Email() { Debug.Log("AccountManager: Calling SignOut"); auth.SignOut(); Firebase.Analytics.FirebaseAnalytics.SetAnalyticsCollectionEnabled(false); Crashlytics.ReportUncaughtExceptionsAsFatal = false; isLoginFail = false; user = null; OnAccountSignOut?.Invoke(true); } }