#define USE_LOCAL_LOCALIZATION using IVDataFormat; using IVServerFormat; using System; using System.Collections; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class MainMgr : MonoBehaviour { private static MainMgr curMgr = null; public static int ServerChannelNumber = 1; #region UI [Header("UI")] [SerializeField] private Camera camUI; [SerializeField] private TextMeshProUGUI txtMainStart, txtMainMsg, txtMainVer; [SerializeField] private TextMeshProUGUI txtLoginInfo, txtLoginSv, txtLoginChar; [SerializeField] private GameObject groupLogin, groupServer; [SerializeField] private ButtonIV btnSvHamburger; [SerializeField] private GameObject groupServer_2; [SerializeField] private TextMeshProUGUI[] txtSvNames, txtSvInfos; [SerializeField] ButtonIV[] btnSvSelect; [SerializeField] TextMeshProUGUI[] txtSvNames_2, txtSvInfos_2; [SerializeField] private Transform trfPopup; private IVPp1Button checkNet; private IVPp1Button[] pp1Buttons; private IVPp2Button pp2Button; private IVPpToast toastTop; [SerializeField] GameObject imgMainStart; [SerializeField] Slider loadingBar; [SerializeField] TextMeshProUGUI loadingPercent; [SerializeField] TextMeshProUGUI txtMainServer; [SerializeField] TextMeshProUGUI txtMainServerConfirm; [SerializeField] GameObject objGuestLogin, objGoogleLogin; #endregion UI #region Terms [Header("Terms")] [SerializeField] GameObject objTerms; [SerializeField] TextMeshProUGUI txtTermsTitle; [SerializeField] Toggle[] toggleTermsCheck; [SerializeField] ButtonIV termsConfirm; #endregion private int iLoading = 1; private int iInitFirebase = -1; bool termsAgree = false; bool isFirstLogin = false; #region Base public static bool IsMain() { return curMgr != null; } IEnumerator Start() { curMgr = this; //터치 이펙트 소환 var touchEffect = Instantiate(Resources.Load("Effect/TouchViewer")); touchEffect.UICamera = camUI; //커버 카메라 초기화 및 홀드 CoverCamera.Init(); CoverCamera.SetCamera(camUI); CoverCamera.Hold(); { txtMainVer.text = FormatString.AppVersion(); LoadServerAndMain(); IVCameraController.SSetTrace(false); TimeUtils.SetNetworkTime(DateTime.UtcNow); //외부 연동 AnalyticsMgr.Init(); SvConnectManager.Instance.Init(); #if !USE_LOCAL_LOCALIZATION SvConnectManager.Instance.RequestSvString(true, 2, UrlApi.GetAssetUrl(UrlApi.AsLocalize), ALocalizeSucc, ALocalizeFail); #else txtMainMsg.text = LocalizationText.GetText("checking_ver"); SvConnectManager.Instance.RequestSvGet(true, 2, UrlApi.GetUrl(UrlApi.GameVer), typeof(dGame), ACheckVerSucc, ACheckVerFail, false, false); #endif SvConnectManager.Instance.RequestEventImageList(); SingleMgr.Instance.Init(); yield return null; //UI 세팅 pp1Buttons = trfPopup.Find("popup1Buttons").GetComponentsInChildren(true); pp2Button = trfPopup.Find("popup2Button").GetComponent(); toastTop = trfPopup.Find("toastTop").GetComponent(); checkNet = trfPopup.Find("CheckNetwork").GetChild(0).GetComponent(); for (int i = 0; i < pp1Buttons.Length; i++) pp1Buttons[i].Init(); pp2Button.Init(); toastTop.Init(); checkNet.Init(); groupLogin.SetActive(false); groupServer.SetActive(false); txtMainStart.gameObject.SetActive(false); imgMainStart.SetActive(false); txtMainStart.text = "Touch to Start"; txtMainMsg.text = "… N O W L O A D I N G …"; txtMainMsg.gameObject.SetActive(true); txtMainServer.text = FormatString.StringFormat(LocalizationText.GetText("server_num"), ServerChannelNumber.ToString()); txtLoginInfo.text = LocalizationText.GetText("main_servertitle"); txtLoginSv.text = LocalizationText.GetText("all_server"); txtLoginChar.text = LocalizationText.GetText("all_char"); if (isFirstLogin) { btnSvHamburger.gameObject.SetActive(false); } } CoverCamera.Release(); iLoading--; } void LoadServerAndMain() { if(!ES3.KeyExists("Server", Global.ES3_StartMain)) { isFirstLogin = true; ES3.Save("Server", 1, Global.ES3_StartMain); } ServerChannelNumber = ES3.Load("Server", Global.ES3_StartMain); if (!ES3.KeyExists("Terms", Global.ES3_StartMain)) { ES3.Save("Terms", false, Global.ES3_StartMain); } termsAgree = ES3.Load("Terms", Global.ES3_StartMain); if (!ES3.KeyExists("FirstLogin", Global.ES3_StartMain)) { ES3.Save("FirstLogin", true, Global.ES3_StartMain); } isFirstLogin = ES3.Load("FirstLogin", Global.ES3_StartMain); } #endregion Base #region terms void OpenTerms() { txtMainMsg.gameObject.SetActive(false); objTerms.SetActive(true); #if false txtTermsTitle.text = LocalizationText.GetText("terms_title"); for (int i = 0; i < txtTermsCheck.Length; i++) { txtTermsCheck[i].text = LocalizationText.GetText(FormatString.StringFormat("terms_{0}", i + 1)); } for (int i = 0; i < txtTermsViewBtn.Length; i++) { txtTermsViewBtn[i].text = LocalizationText.GetText("all_see"); } #endif } public void CheckTermsInteractive() { SoundMgr.PlaySfx(SoundName.BtnPress); if (toggleTermsCheck[0].isOn && toggleTermsCheck[1].isOn) { termsConfirm.interactable = true; } else { termsConfirm.interactable = false; } SettingMgr.StartSwitchNotify(toggleTermsCheck[2].isOn); SettingMgr.StartSwitchNightNotify(toggleTermsCheck[3].isOn); } public void CheckAllTermsInteractive() { for (int i = 0; i < toggleTermsCheck.Length; i++) { toggleTermsCheck[i].isOn = true; } SoundMgr.PlaySfx(SoundName.BtnPress); termsConfirm.interactable = true; SettingMgr.StartSwitchNotify(true); SettingMgr.StartSwitchNightNotify(true); } //TODO: 수정 필요 public void TermsCheck() { if (toggleTermsCheck[0].isOn && toggleTermsCheck[1].isOn) { objTerms.SetActive(false); termsAgree = true; SoundMgr.PlaySfx(SoundName.BtnPress); ES3.Save("Terms", termsAgree, Global.ES3_StartMain); SSetLoginUi(0); } } public void Terms1OpenURL() { SoundMgr.PlaySfx(SoundName.BtnPress); Application.OpenURL(LocalizationText.GetText(Global.MURL_Terms)); } public void Terms2OpenURL() { SoundMgr.PlaySfx(SoundName.BtnPress); Application.OpenURL(LocalizationText.GetText(Global.MURL_Privacy)); } #endregion #region Localize & Version & Inspect #if !USE_LOCAL_LOCALIZATION // 통신 실패 - 로컬라이즈. private void ALocalizeFail(SvError error) { Logger.LogError("LocalizationText load fail."); OpenPopup1Button("Failed to connect to server. Please restart the game.\nIf the same problem repeats, please check the network connection.", SingleMgr.GameFinishOnly, "Confirm", "OK"); } // 통신 성공 - 로컬라이즈. private void ALocalizeSucc(string strresult) { if (string.IsNullOrEmpty(strresult)) { ALocalizeFail(new SvError(eErrorCode.NULL_OR_EMPTY)); return; } LocalizationText.CreateContent(strresult); txtMainMsg.text = LocalizationText.GetText("checking_ver"); SvConnectManager.Instance.RequestSvGet(true, 2, UrlApi.GetUrl(UrlApi.GameVer), typeof(dGame), ACheckVerSucc, ACheckVerFail, false, false); } #endif // 통신 실패 - 게임 버전/점검. private void ACheckVerFail(SvError error) { } // 통신 성공 - 게임 버전/점검. private void ACheckVerSucc(object result) { dGame data = result as dGame; if (data == null) { ACheckVerFail(new SvError(eErrorCode.NULL_OR_EMPTY)); return; } TimeUtils.SetNetworkTime(data.serverTime); // 점검 처리. if (data.isUpdate) { OpenUpdateNotificationPopup(data.updateStartAt, data.updateEndAt); return; } #if VER_ONESTORE int iminver = data.oneMin; int imaxver = data.oneMax; SingleManager.B_CCheck = Global.CVer <= data.oneCouponMax; #elif UNITY_IOS int iminver = data.iosMin; int imaxver = data.iosMax; SingleManager.B_CCheck = Global.CVer <= data.iosCouponMax && data.iosCouponEnable; #else int iminver = data.aosMin; int imaxver = data.aosMax; SingleMgr.B_CCheck = Global.CVer <= data.aosCouponMax; #endif // 현재 게임 버전이 필요 최소 버전보다 낮을 경우 업데이트 필요. if (Global.GameVer < iminver) { txtMainMsg.text = LocalizationText.GetText("error_newclient"); OpenPopup1Button(LocalizationText.GetText("error_newclient"), SingleMgr.GameUpdate, LocalizationText.GetText("all_update"), LocalizationText.GetText("all_update"), false); return; } #if VER_DEV || VER_TEST || VER_ZOMBIE AddressableMgr.Init(); #else // 라이브 버전에서 현재 게임 버전이 최대 버전보다 높을 경우 데브로 연결. if (Global.GameVer > imaxver) { //TODO: dev로 연결 } else { AddressableMgr.Init(); } #endif SoundMgr.SPlayBgm(BGM.intro); SvConnectManager.Instance.RequestSvString(true, 2, UrlApi.GetAssetUrl(UrlApi.AsBanWord), ABanWordSucc, ABanWordFail); DataHandler.SetUpdateNoticeInfo(data.isNotice, data.updateStartAt, data.updateMsg); txtMainMsg.text = LocalizationText.GetText("loading_now"); if (!termsAgree) { OpenTerms(); } else { SSetLoginUi(0); } } // 통신 실패 - 금칙어. private void ABanWordFail(SvError error) { Logger.LogError("BanWord load fail."); OpenPopup1Button("Failed to connect to server. Please restart the game.\nIf the same problem repeats, please check the network connection.", SingleMgr.GameFinishOnly); } // 통신 성공 - 금칙어. private void ABanWordSucc(string strresult) { if (string.IsNullOrEmpty(strresult)) { ABanWordFail(new SvError(eErrorCode.NULL_OR_EMPTY)); return; } ChatFilter.BanWordFilter.CreateContent(strresult); } // 점검 팝업 표시. public void OpenUpdateNotificationPopup(DateTime utcstart, DateTime utcend) { txtMainMsg.text = LocalizationText.GetText("exc_inspectmsg"); if (TimeUtils.Now() >= utcstart && TimeUtils.Now() <= utcend) { OpenPopup1Button(string.Format(LocalizationText.GetText("msg_inspecttime"), TimeUtils.ToLocalTime(utcstart), TimeUtils.ToLocalTime(utcend)), SingleMgr.GameFinishOnly); } else { OpenPopup1Button(LocalizationText.GetText("exc_inspectmsg"), SingleMgr.GameFinishOnly); } } #endregion Localize & Version & Inspect #region Login // 로그인 UI 표시. public static void SSetLoginUi(int isettype) { if (curMgr != null) { if (curMgr.iInitFirebase < 0) { curMgr.iInitFirebase = isettype; return; } if (isettype > 0) curMgr.iInitFirebase = isettype; // 이전에 로그인 한 유저 정보가 없음. 로그인 버튼 표시. if (curMgr.iInitFirebase == 0) { curMgr.groupLogin.SetActive(true); curMgr.groupServer.SetActive(false); curMgr.txtMainStart.gameObject.SetActive(true); curMgr.txtMainMsg.gameObject.SetActive(false); } // 이전에 로그인 한 유저 정보가 있음. 마스터 로그인. else { curMgr.iLoading++; curMgr.groupLogin.SetActive(false); curMgr.groupServer.SetActive(false); curMgr.txtMainStart.gameObject.SetActive(false); curMgr.txtMainMsg.gameObject.SetActive(true); curMgr.PlatformLoginSucc(); } //문제가 생기면 이거 떄문임 if (curMgr.isFirstLogin) { curMgr.groupLogin.SetActive(false); curMgr.txtMainStart.gameObject.SetActive(false); curMgr.OpenFirstLoginBtn(); } } } public void OpenFirstLoginBtn() { txtMainMsg.gameObject.SetActive(false); objGuestLogin.SetActive(true); } // 게스트 로그인. public void BtnLoginPress() { if (iLoading > 0) return; iLoading++; txtMainMsg.text = LocalizationText.GetText("checking_user"); groupLogin.SetActive(false); groupServer.SetActive(false); txtMainStart.gameObject.SetActive(false); curMgr.imgMainStart.SetActive(false); txtMainMsg.gameObject.SetActive(true); objGuestLogin.SetActive(false); objGoogleLogin.SetActive(false); btnSvHamburger.interactable = false; //나중에 로그인 정보 저장할 수 있게 되면 분할해둬야 함. SingleMgr.AuthAnonymous(); SoundMgr.PlaySfx(SoundName.BtnPress); } //일반 로그인. public static void GoogleLoginPress() { if (curMgr.iLoading > 0) return; curMgr.iLoading++; curMgr.txtMainMsg.text = LocalizationText.GetText("checking_user"); curMgr.groupLogin.SetActive(false); curMgr.groupServer.SetActive(false); curMgr.txtMainStart.gameObject.SetActive(false); curMgr.imgMainStart.SetActive(false); curMgr.txtMainMsg.gameObject.SetActive(true); curMgr.objGuestLogin.SetActive(false); curMgr.objGoogleLogin.SetActive(false); //OpenPopup1Button("xptmxm"); SingleMgr.AuthAnonymous(); SoundMgr.PlaySfx(SoundName.BtnPress); } public static void SLoginFail() { if (curMgr != null) { curMgr.iLoading--; SSetLoginUi(0); } } public static void SPlatformLoginSucc() { curMgr?.PlatformLoginSucc(); } // 플랫폼 로그인(파이어베이스 등) 성공. 마스터 로그인 시도. private void PlatformLoginSucc() { txtMainMsg.text = LocalizationText.GetText("checking_account"); if (isFirstLogin) { SvConnectManager.Instance.RequestSvPost(true, 1, UrlApi.GetUrl(UrlApi.MasterLogin), typeof(nMasterData), curMgr.AMasterLoginSucc_2, curMgr.AMasterLoginFail, new nToken(SingleMgr.UserToken), false, true, 0); } else { SvConnectManager.Instance.RequestSvPost(true, 1, UrlApi.GetUrl(UrlApi.Login), typeof(nIdLv), curMgr.ALoginSucc, curMgr.ALoginFail, new nToken(SingleMgr.UserToken, ServerChannelNumber), false, true, ServerChannelNumber); } } // 통신 성공 - 마스터 로그인. 서버 선택 UI 표시. private void AMasterLoginSucc_2(object result, object request) { nMasterData data = result as nMasterData; if (data == null) { AMasterLoginFail(new SvError(eErrorCode.NULL_OR_EMPTY), request); return; } txtMainServerConfirm.text = LocalizationText.GetText("all_confirm"); txtMainMsg.gameObject.SetActive(false); string strsv = LocalizationText.GetText("server_num"); for (int i = 0; i < txtSvNames_2.Length; i++) { txtSvInfos_2[i].text = LocalizationText.GetText("server_empty"); } for (int i = 0; i < txtSvNames_2.Length; i++) { txtSvNames_2[i].text = FormatString.StringFormat(strsv, (i + 1).ToString()); if (i < data.user.Length && !string.IsNullOrEmpty(data.user[i].userCode)) { txtSvInfos_2[data.user[i].server - 1].text = FormatString.TextLvName(data.user[i].playerLv, data.user[i].playerName); } } for (int i = 0; i < btnSvSelect.Length; i++) { btnSvSelect[i].interactable = true; } btnSvSelect[ServerChannelNumber - 1].interactable = false; groupServer_2.SetActive(true); iLoading--; } // 통신 실패 - 마스터 로그인. private void AMasterLoginFail(SvError error, object request) { iLoading--; SSetLoginUi(0); } //새 서버 선택창 public void OpenSelectServerWindow() { objGuestLogin.SetActive(false); objGoogleLogin.SetActive(false); txtMainServerConfirm.text = LocalizationText.GetText("all_confirm"); SoundMgr.PlaySfx(SoundName.BtnPress); SvConnectManager.Instance.RequestSvPost(true, 1, UrlApi.GetUrl(UrlApi.MasterLogin), typeof(nMasterData), curMgr.AMasterLoginSucc_2, curMgr.AMasterLoginFail, new nToken(SingleMgr.UserToken), false, true, 0); } //서버 선택. Ver 2 서버선택의 버튼 public void SelectServerToggle(int iserver) { SoundMgr.PlaySfx(SoundName.BtnPress); for (int i = 0; i < btnSvSelect.Length; i++) { btnSvSelect[i].interactable = true; } ServerChannelNumber = iserver; btnSvSelect[iserver - 1].interactable = false; } public void ConfirmServer() { //서버 표기 txtMainServer.text = FormatString.StringFormat(LocalizationText.GetText("server_num"), ServerChannelNumber.ToString()); groupServer_2.SetActive(false); ES3.Save("Server", ServerChannelNumber, Global.ES3_StartMain); if (isFirstLogin) { isFirstLogin = false; ES3.Save("FirstLogin", isFirstLogin, Global.ES3_StartMain); BtnSelectServer(ServerChannelNumber); txtMainServer.text = FormatString.StringFormat(LocalizationText.GetText("server_num"), ServerChannelNumber.ToString()); btnSvHamburger.gameObject.SetActive(true); } SoundMgr.PlaySfx(SoundName.BtnPress); } // 서버 선택.Ver 1 서버선택의 버튼 public void BtnSelectServer(int iserver) { if (iLoading > 0) return; iLoading++; ServerChannelNumber = iserver; txtMainMsg.text = LocalizationText.GetText("checking_server"); txtMainMsg.gameObject.SetActive(true); groupServer.SetActive(false); SvConnectManager.Instance.RequestSvPost(true, 1, UrlApi.GetUrl(UrlApi.Login), typeof(nIdLv), curMgr.ALoginSucc, curMgr.ALoginFail, new nToken(SingleMgr.UserToken, iserver), false, true, ServerChannelNumber); } // 통신 실패 - 로그인(서버 선택). private void ALoginFail(SvError error, object request) { groupServer.SetActive(true); txtMainMsg.gameObject.SetActive(false); iLoading--; } // 통신 성공 - 로그인(서버 선택). private void ALoginSucc(object result, object request) { txtMainMsg.text = LocalizationText.GetText("loading_system"); loadingBar.gameObject.SetActive(true); loadingBar.value = 0; SvConnectManager.Instance.RequestSvGet(true, 0, UrlApi.GetUrl(UrlApi.System), typeof(nSystemData), curMgr.ASystemSucc, curMgr.ASystemFail, false, true, ServerChannelNumber); } #endregion Login #region Load Datas // 통신 실패 - 시스템 데이터. private void ASystemFail(SvError error) { OpenPopup1Button(LocalizationText.GetText("msg_loaddatarestart"), SingleMgr.GameFinishOnly); } // 통신 성공 - 시스템 데이터. private void ASystemSucc(object result) { nSystemData data = result as nSystemData; if (data == null) { ASystemFail(new SvError(eErrorCode.NULL_OR_EMPTY)); return; } StartCoroutine(LoadSysData(data)); } // 시스템 데이터 로드. private IEnumerator LoadSysData(nSystemData data) { yield return DataHandler.InitSystemData(data); DataHandler.PutGoldInterval1000(); txtMainMsg.text = LocalizationText.GetText("loading_data"); SvConnectManager.Instance.RequestSvGet(true, 0, UrlApi.GetUrl(UrlApi.Play), typeof(nPlayData), curMgr.APlaySucc, curMgr.APlayFail, false, true, ServerChannelNumber); } // 통신 실패 - 플레이 데이터. private void APlayFail(SvError error) { OpenPopup1Button(LocalizationText.GetText("msg_loaddatarestart"), SingleMgr.GameFinishOnly); } // 통신 성공 - 플레이 데이터. private void APlaySucc(object result) { nPlayData data = result as nPlayData; if (data == null) { APlayFail(new SvError(eErrorCode.NULL_OR_EMPTY)); return; } StartCoroutine(LoadPlayData(data)); } // 플레이 데이터 로드. private IEnumerator LoadPlayData(nPlayData data) { yield return DataHandler.InitPlayData(data); SingleMgr.I_OfflineTime = (int)(TimeUtils.Now() - DataHandler.PlayData.lastTime).TotalSeconds; SingleMgr.CheckSaveData(true); BuffMgr.Instance.SetGuardianAwakenStat(); BuffMgr.Instance.CalcAllStat(); StartCoroutine(LoadingScene("GameScene")); } #endregion Load Datas // 게임씬으로 이동. private IEnumerator LoadingScene(string sceneName) { Logger.Log("LoadingScene " + AddressableMgr.I_LoadingCnt.ToString()); txtMainMsg.text = LocalizationText.GetText("loading_scene"); while (AddressableMgr.I_LoadingCnt > 0) yield return YieldInstructionCache.WaitForSeconds(0.5f); AsyncOperation scene = SceneManager.LoadSceneAsync(sceneName); scene.allowSceneActivation = false; const float maxRate = 2.0f; while (scene.progress < 0.89f) { UpdateLoadingBar(scene.progress / maxRate); yield return null; } const float extraTime = 2.0f; float extraTimeElapsed = 0.0f; while(extraTimeElapsed < extraTime) { extraTimeElapsed = Math.Min(extraTimeElapsed + Time.fixedDeltaTime, extraTime); UpdateLoadingBar((1.0f + (extraTimeElapsed / extraTime)) / maxRate); yield return null; } scene.allowSceneActivation = true; } void UpdateLoadingBar(float percent) { loadingPercent.text = FormatString.StringFormat("{0:F0}%", percent * 100); loadingBar.value = percent; } #region Popup public static void SOpenPopupCheckNet(string strmsg, Action actionyes = null, string strtitle = null, string stryes = null, bool bclose = true, float ftime = 0f, int igroup = -1) { if (curMgr != null) curMgr.OepnPopupNet(strmsg, actionyes, strtitle, stryes, bclose, ftime, igroup); } private void OepnPopupNet(string strmsg, Action actionyes = null, string strtitle = null, string stryes = null, bool bclose = true, float ftime = 0f, int igroup = -1) { if (checkNet == null) return; if (checkNet.IsOpen()) return; checkNet.Open(strmsg, actionyes, strtitle, stryes, bclose, ftime, igroup); return; } public static void SOpenPopup1Button(string strmsg, Action actionyes = null, string strtitle = null, string stryes = null, bool bclose = true, float ftime = 0f) { if (curMgr != null) curMgr.OpenPopup1Button(strmsg, actionyes, strtitle, stryes, bclose, ftime); } // 1버튼 팝업 열기. private void OpenPopup1Button(string strmsg, Action actionyes = null, string strtitle = null, string stryes = null, bool bclose = true, float ftime = 0f) { if (pp1Buttons == null) return; for (int i = 0; i < pp1Buttons.Length; i++) { // 이미 열려있는 팝업. if (pp1Buttons[i].IsOpen()) continue; pp1Buttons[i].Open(strmsg, actionyes, strtitle, stryes, bclose, ftime); return; } } public static void SOpenPopup2Button(string strmsg, Action actionyes = null, Action actionno = null, string strtitle = null, string stryes = null, string strno = null) { if (curMgr != null) curMgr.OpenPopup2Button(strmsg, actionyes, actionno, strtitle, stryes, strno); } // 2버튼 팝업 열기. private void OpenPopup2Button(string strmsg, Action actionyes = null, Action actionno = null, string strtitle = null, string stryes = null, string strno = null) { if (pp2Button == null) return; pp2Button.Open(strmsg, actionyes, actionno, strtitle, stryes, strno); } public static void SOpenToast(string strmsg, float ftime = 2f) { if (curMgr != null) curMgr.OpenToast(strmsg, ftime); } // 2버튼 팝업 열기. private void OpenToast(string strmsg, float ftime = 2f) { if (toastTop == null) return; toastTop.Open(strmsg, ftime); } #endregion Popup }