コード例 #1
0
        public void OnLogin(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseUserLoginMessage response)
        {
            LoggingIn = false;
            string storingUsername = string.Empty;
            string storingPassword = string.Empty;

            if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
            {
                if (onLoginFail != null)
                {
                    onLoginFail.Invoke();
                }
                return;
            }
            if (toggleAutoLogin != null && toggleAutoLogin.isOn)
            {
                // Store password
                PlayerPrefs.SetString(keyUsername, storingUsername);
                PlayerPrefs.SetString(keyPassword, storingPassword);
                PlayerPrefs.Save();
            }
            if (onLoginSuccess != null)
            {
                onLoginSuccess.Invoke();
            }
        }
コード例 #2
0
        private void OnRequestedDeleteCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                return;
            }
            // Proceed response
            ResponseDeleteCharacterMessage message = response as ResponseDeleteCharacterMessage;

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (message.error)
                {
                case ResponseDeleteCharacterMessage.Error.NotLoggedin:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_NOT_LOGGED_IN.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                break;

            default:
                // Reload characters
                LoadCharacters();
                break;
            }
        }
コード例 #3
0
 /// <summary>
 /// Response callback for MoveAllItemsFromStorage
 /// </summary>
 public static void ResponseMoveAllItemsFromStorage(ResponseHandlerData requestHandler, AckResponseCode responseCode, ResponseMoveAllItemsFromStorageMessage response)
 {
     ClientGenericActions.ClientReceiveGameMessage(response.message);
     if (onResponseMoveAllItemsFromStorage != null)
     {
         onResponseMoveAllItemsFromStorage.Invoke(requestHandler, responseCode, response);
     }
 }
コード例 #4
0
 private void OnUserLogout(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
 {
     if (responseCode == AckResponseCode.Success)
     {
         ClearHistory();
         Next(uiLogin);
     }
 }
コード例 #5
0
 private void OnRequestedSelectCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseSelectCharacterMessage response)
 {
     if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
     {
         return;
     }
     MMOClientInstance.Singleton.StartMapClient(response.sceneName, response.networkAddress, response.networkPort);
 }
コード例 #6
0
 private void OnRequestedDeleteCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseDeleteCharacterMessage response)
 {
     if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
     {
         return;
     }
     // Reload characters
     LoadCharacters();
 }
コード例 #7
0
 private void HandleResponseAppServerAddress(
     ResponseHandlerData responseHandler,
     AckResponseCode responseCode,
     ResponseAppServerAddressMessage response)
 {
     if (onResponseAppServerAddress != null)
     {
         onResponseAppServerAddress.Invoke(responseCode, response.peerInfo);
     }
 }
コード例 #8
0
 private void OnValidateAccessToken(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
 {
     if (responseCode == AckResponseCode.Success)
     {
         if (onValidateAccessTokenSuccess != null)
         {
             onValidateAccessTokenSuccess.Invoke();
         }
     }
 }
コード例 #9
0
        private void OnRequestUserLogout(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response, ResponseDelegate callback)
        {
            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            UserId            = string.Empty;
            AccessToken       = string.Empty;
            SelectCharacterId = string.Empty;
        }
コード例 #10
0
 private void OnRequestedCreateCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseCreateCharacterMessage response)
 {
     if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
     {
         return;
     }
     if (eventOnCreateCharacter != null)
     {
         eventOnCreateCharacter.Invoke();
     }
 }
コード例 #11
0
        private async UniTaskVoid OnRequestedDeleteCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseDeleteCharacterMessage response)
        {
            await UniTask.Yield();

            if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
            {
                return;
            }
            // Reload characters
            LoadCharacters();
        }
コード例 #12
0
        public void OnLogin(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            LoggingIn = false;
            string storingUsername = string.Empty;
            string storingPassword = string.Empty;

            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                if (onLoginFail != null)
                {
                    onLoginFail.Invoke();
                }
                return;
            }
            ResponseUserLoginMessage castedResponse = response as ResponseUserLoginMessage;

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (castedResponse.error)
                {
                case ResponseUserLoginMessage.Error.AlreadyLogin:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_ALREADY_LOGGED_IN.ToString());
                    break;

                case ResponseUserLoginMessage.Error.InvalidUsernameOrPassword:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_INVALID_USERNAME_OR_PASSWORD.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                if (onLoginFail != null)
                {
                    onLoginFail.Invoke();
                }
                break;

            default:
                if (toggleAutoLogin != null && toggleAutoLogin.isOn)
                {
                    // Store password
                    PlayerPrefs.SetString(keyPassword, storingPassword);
                    PlayerPrefs.Save();
                }
                if (onLoginSuccess != null)
                {
                    onLoginSuccess.Invoke();
                }
                break;
            }
        }
コード例 #13
0
        private void OnRequestSelectCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response, string characterId, ResponseDelegate callback)
        {
            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            SelectCharacterId = string.Empty;
            if (responseCode == AckResponseCode.Success)
            {
                SelectCharacterId = characterId;
            }
        }
コード例 #14
0
        private async UniTaskVoid OnRequestUserLogout(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response, ResponseDelegate <INetSerializable> callback)
        {
            await UniTask.Yield();

            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            GameInstance.UserId              = string.Empty;
            GameInstance.UserToken           = string.Empty;
            GameInstance.SelectedCharacterId = string.Empty;
        }
コード例 #15
0
        public void OnRegister(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            Registering = false;
            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                if (onRegisterFail != null)
                {
                    onRegisterFail.Invoke();
                }
                return;
            }
            ResponseUserRegisterMessage castedResponse = response as ResponseUserRegisterMessage;

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (castedResponse.error)
                {
                case ResponseUserRegisterMessage.Error.TooShortUsername:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_USERNAME_TOO_SHORT.ToString());
                    break;

                case ResponseUserRegisterMessage.Error.TooLongUsername:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_USERNAME_TOO_LONG.ToString());
                    break;

                case ResponseUserRegisterMessage.Error.TooShortPassword:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_PASSWORD_TOO_SHORT.ToString());
                    break;

                case ResponseUserRegisterMessage.Error.UsernameAlreadyExisted:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_USERNAME_EXISTED.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                if (onRegisterFail != null)
                {
                    onRegisterFail.Invoke();
                }
                break;

            default:
                if (onRegisterSuccess != null)
                {
                    onRegisterSuccess.Invoke();
                }
                break;
            }
        }
コード例 #16
0
 public void OnAppServerRegistered(
     ResponseHandlerData responseHandler,
     AckResponseCode responseCode,
     ResponseAppServerRegisterMessage response)
 {
     if (responseCode == AckResponseCode.Success)
     {
         IsRegisteredToCentralServer = true;
     }
     if (onAppServerRegistered != null)
     {
         onAppServerRegistered.Invoke(responseCode);
     }
 }
コード例 #17
0
 private void HandleResponseAppServerRegister(
     ResponseHandlerData responseHandler,
     AckResponseCode responseCode,
     ResponseAppServerRegisterMessage response)
 {
     if (responseCode == AckResponseCode.Success)
     {
         Logging.Log(LogTag, "App Registered successfully");
         IsAppRegistered = true;
     }
     if (onResponseAppServerRegister != null)
     {
         onResponseAppServerRegister.Invoke(responseCode);
     }
 }
コード例 #18
0
        private async UniTaskVoid OnRequestSelectCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseSelectCharacterMessage response, string characterId, ResponseDelegate <ResponseSelectCharacterMessage> callback)
        {
            await UniTask.Yield();

            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            GameInstance.SelectedCharacterId = string.Empty;
            if (responseCode == AckResponseCode.Success)
            {
                GameInstance.SelectedCharacterId = characterId;
            }
        }
コード例 #19
0
 public void OnLogin(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseUserLoginMessage response)
 {
     if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
     {
         if (onLoginFail != null)
         {
             onLoginFail.Invoke();
         }
         return;
     }
     if (onLoginSuccess != null)
     {
         onLoginSuccess.Invoke();
     }
 }
コード例 #20
0
        private void OnRequestValidateAccessToken(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response, ResponseDelegate callback)
        {
            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            UserId      = string.Empty;
            AccessToken = string.Empty;
            if (responseCode == AckResponseCode.Success)
            {
                ResponseValidateAccessTokenMessage castedResponse = response as ResponseValidateAccessTokenMessage;
                UserId      = castedResponse.userId;
                AccessToken = castedResponse.accessToken;
            }
        }
コード例 #21
0
 public void OnRegister(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseUserRegisterMessage response)
 {
     Registering = false;
     if (responseCode.ShowUnhandledResponseMessageDialog(response.message))
     {
         if (onRegisterFail != null)
         {
             onRegisterFail.Invoke();
         }
         return;
     }
     if (onRegisterSuccess != null)
     {
         onRegisterSuccess.Invoke();
     }
 }
コード例 #22
0
        private void OnRequestedCreateCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                return;
            }
            // Proceed response
            ResponseCreateCharacterMessage castedResponse = response as ResponseCreateCharacterMessage;

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (castedResponse.error)
                {
                case ResponseCreateCharacterMessage.Error.NotLoggedin:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_NOT_LOGGED_IN.ToString());
                    break;

                case ResponseCreateCharacterMessage.Error.InvalidData:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_INVALID_DATA.ToString());
                    break;

                case ResponseCreateCharacterMessage.Error.TooShortCharacterName:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_CHARACTER_NAME_TOO_SHORT.ToString());
                    break;

                case ResponseCreateCharacterMessage.Error.TooLongCharacterName:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_CHARACTER_NAME_TOO_LONG.ToString());
                    break;

                case ResponseCreateCharacterMessage.Error.CharacterNameAlreadyExisted:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_CHARACTER_NAME_EXISTED.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                break;

            default:
                if (eventOnCreateCharacter != null)
                {
                    eventOnCreateCharacter.Invoke();
                }
                break;
            }
        }
コード例 #23
0
        private async UniTaskVoid OnRequestValidateAccessToken(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseValidateAccessTokenMessage response, ResponseDelegate <ResponseValidateAccessTokenMessage> callback)
        {
            await UniTask.Yield();

            if (callback != null)
            {
                callback.Invoke(responseHandler, responseCode, response);
            }

            GameInstance.UserId    = string.Empty;
            GameInstance.UserToken = string.Empty;
            if (responseCode == AckResponseCode.Success)
            {
                GameInstance.UserId    = response.userId;
                GameInstance.UserToken = response.accessToken;
            }
        }
コード例 #24
0
        private void OnRequestedSelectCharacter(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                return;
            }
            // Proceed response
            ResponseSelectCharacterMessage castedResponse = response as ResponseSelectCharacterMessage;

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (castedResponse.error)
                {
                case ResponseSelectCharacterMessage.Error.NotLoggedin:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_NOT_LOGGED_IN.ToString());
                    break;

                case ResponseSelectCharacterMessage.Error.AlreadySelectCharacter:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_ALREADY_SELECT_CHARACTER.ToString());
                    break;

                case ResponseSelectCharacterMessage.Error.InvalidCharacterData:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_INVALID_CHARACTER_DATA.ToString());
                    break;

                case ResponseSelectCharacterMessage.Error.MapNotReady:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_MAP_SERVER_NOT_READY.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                break;

            default:
                MMOClientInstance.Singleton.StartMapClient(castedResponse.sceneName, castedResponse.networkAddress, castedResponse.networkPort);
                break;
            }
        }
 private void OnRequestSpawnMap(ResponseHandlerData requestHandler, AckResponseCode responseCode, INetSerializable response, string instanceId)
 {
     if (responseCode == AckResponseCode.Error ||
         responseCode == AckResponseCode.Timeout)
     {
         // Remove warping characters who warping to instance map
         HashSet <uint> instanceMapWarpingCharacters;
         if (instanceMapWarpingCharactersByInstanceId.TryGetValue(instanceId, out instanceMapWarpingCharacters))
         {
             BasePlayerCharacterEntity playerCharacterEntity;
             foreach (uint warpingCharacter in instanceMapWarpingCharacters)
             {
                 if (Assets.TryGetSpawnedObject(warpingCharacter, out playerCharacterEntity))
                 {
                     playerCharacterEntity.IsWarping = false;
                     ServerGameMessageHandlers.SendGameMessage(playerCharacterEntity.ConnectionId, UITextKeys.UI_ERROR_SERVICE_NOT_AVAILABLE);
                 }
             }
             instanceMapWarpingCharactersByInstanceId.TryRemove(instanceId, out _);
         }
         instanceMapWarpingLocations.TryRemove(instanceId, out _);
     }
 }
コード例 #26
0
        private void OnRequestedCharacters(ResponseHandlerData responseHandler, AckResponseCode responseCode, INetSerializable response)
        {
            // Clear character list
            CacheCharacterSelectionManager.Clear();
            CacheCharacterList.HideAll();
            // Unable buttons
            buttonStart.gameObject.SetActive(false);
            buttonDelete.gameObject.SetActive(false);
            // Remove all models
            characterModelContainer.RemoveChildren();
            CharacterModelById.Clear();
            // Remove all cached data
            PlayerCharacterDataById.Clear();
            // Don't make character list if timeout
            if (responseCode == AckResponseCode.Timeout)
            {
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), LanguageManager.GetText(UITextKeys.UI_ERROR_CONNECTION_TIMEOUT.ToString()));
                return;
            }
            // Proceed response
            ResponseCharactersMessage  castedResponse       = response as ResponseCharactersMessage;
            List <PlayerCharacterData> selectableCharacters = new List <PlayerCharacterData>();

            switch (responseCode)
            {
            case AckResponseCode.Error:
                string errorMessage = string.Empty;
                switch (castedResponse.error)
                {
                case ResponseCharactersMessage.Error.NotLoggedin:
                    errorMessage = LanguageManager.GetText(UITextKeys.UI_ERROR_NOT_LOGGED_IN.ToString());
                    break;
                }
                UISceneGlobal.Singleton.ShowMessageDialog(LanguageManager.GetText(UITextKeys.UI_LABEL_ERROR.ToString()), errorMessage);
                break;

            default:
                selectableCharacters = castedResponse.characters;
                break;
            }

            // Show list of created characters
            for (int i = selectableCharacters.Count - 1; i >= 0; --i)
            {
                PlayerCharacterData selectableCharacter = selectableCharacters[i];
                if (selectableCharacter == null ||
                    !GameInstance.PlayerCharacterEntities.ContainsKey(selectableCharacter.EntityId) ||
                    !GameInstance.PlayerCharacters.ContainsKey(selectableCharacter.DataId))
                {
                    // If invalid entity id or data id, remove from selectable character list
                    selectableCharacters.RemoveAt(i);
                }
            }

            if (GameInstance.Singleton.maxCharacterSaves > 0 &&
                selectableCharacters.Count >= GameInstance.Singleton.maxCharacterSaves)
            {
                eventOnNotAbleToCreateCharacter.Invoke();
            }
            else
            {
                eventOnAbleToCreateCharacter.Invoke();
            }

            // Clear selected character data, will select first in list if available
            selectedPlayerCharacterData = null;

            // Generate list entry by saved characters
            if (selectableCharacters.Count > 0)
            {
                selectableCharacters.Sort(new PlayerCharacterDataLastUpdateComparer().Desc());
                CacheCharacterList.Generate(selectableCharacters, (index, characterData, ui) =>
                {
                    // Cache player character to dictionary, we will use it later
                    PlayerCharacterDataById[characterData.Id] = characterData;
                    // Setup UIs
                    UICharacter uiCharacter = ui.GetComponent <UICharacter>();
                    uiCharacter.Data        = characterData;
                    // Select trigger when add first entry so deactivate all models is okay beacause first model will active
                    BaseCharacterModel characterModel = characterData.InstantiateModel(characterModelContainer);
                    if (characterModel != null)
                    {
                        CharacterModelById[characterData.Id] = characterModel;
                        characterModel.SetEquipWeapons(characterData.EquipWeapons);
                        characterModel.SetEquipItems(characterData.EquipItems);
                        characterModel.gameObject.SetActive(false);
                        CacheCharacterSelectionManager.Add(uiCharacter);
                    }
                });
            }
            else
            {
                eventOnNoCharacter.Invoke();
            }
        }
コード例 #27
0
        private void OnRequestedCharacters(ResponseHandlerData responseHandler, AckResponseCode responseCode, ResponseCharactersMessage response)
        {
            // Clear character list
            CacheCharacterSelectionManager.Clear();
            CacheCharacterList.HideAll();
            // Unable buttons
            buttonStart.gameObject.SetActive(false);
            buttonDelete.gameObject.SetActive(false);
            // Remove all models
            characterModelContainer.RemoveChildren();
            CharacterModelById.Clear();
            // Remove all cached data
            PlayerCharacterDataById.Clear();
            // Proceed response
            List <PlayerCharacterData> selectableCharacters = new List <PlayerCharacterData>();

            if (!responseCode.ShowUnhandledResponseMessageDialog(response.message))
            {
                // Success, so set selectable characters by response's data
                selectableCharacters = response.characters;
            }
            // Show list of created characters
            for (int i = selectableCharacters.Count - 1; i >= 0; --i)
            {
                PlayerCharacterData selectableCharacter = selectableCharacters[i];
                if (selectableCharacter == null ||
                    !GameInstance.PlayerCharacterEntities.ContainsKey(selectableCharacter.EntityId) ||
                    !GameInstance.PlayerCharacters.ContainsKey(selectableCharacter.DataId))
                {
                    // If invalid entity id or data id, remove from selectable character list
                    selectableCharacters.RemoveAt(i);
                }
            }

            if (GameInstance.Singleton.maxCharacterSaves > 0 &&
                selectableCharacters.Count >= GameInstance.Singleton.maxCharacterSaves)
            {
                eventOnNotAbleToCreateCharacter.Invoke();
            }
            else
            {
                eventOnAbleToCreateCharacter.Invoke();
            }

            // Clear selected character data, will select first in list if available
            selectedPlayerCharacterData = null;

            // Generate list entry by saved characters
            if (selectableCharacters.Count > 0)
            {
                selectableCharacters.Sort(new PlayerCharacterDataLastUpdateComparer().Desc());
                CacheCharacterList.Generate(selectableCharacters, (index, characterData, ui) =>
                {
                    // Cache player character to dictionary, we will use it later
                    PlayerCharacterDataById[characterData.Id] = characterData;
                    // Setup UIs
                    UICharacter uiCharacter = ui.GetComponent <UICharacter>();
                    uiCharacter.Data        = characterData;
                    // Select trigger when add first entry so deactivate all models is okay beacause first model will active
                    BaseCharacterModel characterModel = characterData.InstantiateModel(characterModelContainer);
                    if (characterModel != null)
                    {
                        CharacterModelById[characterData.Id] = characterModel;
                        characterModel.SetEquipWeapons(characterData.EquipWeapons);
                        characterModel.SetEquipItems(characterData.EquipItems);
                        characterModel.gameObject.SetActive(false);
                        CacheCharacterSelectionManager.Add(uiCharacter);
                    }
                });
            }
            else
            {
                eventOnNoCharacter.Invoke();
            }
        }