using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using BrewMonster.Network; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; namespace BrewMonster.UI { /// /// Login Flow: /// 1. Enter username and password /// 2. Click login button /// 3. Login success, get the list of characters /// 4. Open the select character screen /// public class LoginScreenUI : MonoBehaviour { [SerializeField] private TMP_InputField _usernameInputField; [SerializeField] private TMP_InputField _passwordInputField; [SerializeField] private Button _loginButton; [SerializeField] private SelecScreenCharacter _selectCharacterScreen; private List _roleInfos; private List _currentRoles; private RoleInfo _pendingCreatedRole; bool isDoneWorldRender = false; bool isDoneNPCRender = false; private SynchronizationContext context; public AudioClip loginBGM; void Start() { AudioManager.Instance.PlayBGM(loginBGM, 1.5f); _loginButton.onClick.AddListener(OnLoginButtonClicked); context = SynchronizationContext.Current; _usernameInputField.text = PlayerPrefs.GetString("username", ""); _passwordInputField.text = PlayerPrefs.GetString("password", ""); } // Update is called once per frame void Update() { if (_roleInfos != null) { _selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter, OnCreateCharacterComplete); _roleInfos = null; } #if UNITY_EDITOR if (Input.GetKeyUp(KeyCode.LeftAlt)) { _usernameInputField.text = "test004"; _passwordInputField.text = "123456"; } if (Input.GetKeyUp(KeyCode.Tab)) { _usernameInputField.text = "test002"; _passwordInputField.text = "123456"; OnLoginButtonClicked(); } #endif } public async void OnLoginButtonClicked() { BMLogger.Log("OnLoginButtonClicked"); string username = _usernameInputField.text; string password = _passwordInputField.text; // UnityGameSession.SetConnectionInfo("103.182.22.52", 29000); UnityGameSession.SetConnectionInfo("103.51.120.195", 29000); PlayerPrefs.SetString("username", username); PlayerPrefs.SetString("password", password); PlayerPrefs.Save(); await UnityGameSession.Login(username, password, OnLoginComplete); _selectCharacterScreen.gameObject.SetActive(true); } /// /// Callback when the login is complete. /// Then get the list of characters /// private void OnLoginComplete(bool result) { if (!result) { BMLogger.LogError("Login failed"); return; } UnityGameSession.GetRoleListAsync(OnGetRoleListComplete); } /// /// Callback when the list of characters is retrieved. /// Then move to the select character screen /// private void OnGetRoleListComplete(List roleInfos) { if (roleInfos == null) { BMLogger.LogError("OnGetRoleListComplete: roleInfos is null"); // Keep whatever is currently shown; don't overwrite UI state with null. return; } // Merge pending created role in case backend list hasn't updated yet. if (_pendingCreatedRole != null) { bool exists = false; for (int i = 0; i < roleInfos.Count; i++) { if (roleInfos[i].roleid == _pendingCreatedRole.roleid) { exists = true; break; } } if (!exists) { // Copy list so we don't mutate a list owned elsewhere. var merged = new List(roleInfos.Count + 1); merged.AddRange(roleInfos); merged.Add(_pendingCreatedRole); roleInfos = merged; } else { // Backend now includes the role; clear pending. _pendingCreatedRole = null; } } BMLogger.Log($"OnGetRoleListComplete: roles={roleInfos.Count}"); _roleInfos = roleInfos; _currentRoles = roleInfos; } private void OnClickSelectCharacter(RoleInfo roleInfo) { UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete); } /// /// Callback when a new character is created. /// Refreshes the role list and keeps the character selection screen visible. /// private void OnCreateCharacterComplete(RoleInfo createdRole) { BMLogger.Log("Character created, refreshing role list..."); if (_selectCharacterScreen != null) { _selectCharacterScreen.gameObject.SetActive(true); } // Ensure the newly created role is visible immediately even if the server role list // hasn't updated yet. if (createdRole != null) { _pendingCreatedRole = createdRole; if (_currentRoles == null) { _currentRoles = new List(); } bool exists = false; for (int i = 0; i < _currentRoles.Count; i++) { if (_currentRoles[i].roleid == createdRole.roleid) { exists = true; break; } } if (!exists) { _currentRoles.Add(createdRole); } _roleInfos = _currentRoles; } else { BMLogger.LogError("OnCreateCharacterComplete: createdRole is null (create-role callback returned null)"); } // NOTE: // Immediately requesting the role list after create has been observed to disconnect // in some server builds. We rely on the createdRole callback to update UI instantly. // A server sync can be done later (e.g., next time you open this screen / re-login). } private void OnSelectRoleComplete(RoleInfo roleInfo) { context.Post(_ => { isDoneWorldRender = false; isDoneNPCRender = false; Action actLoadChar = () => { if (!isDoneNPCRender || !isDoneWorldRender) { return; } }; SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading; SceneLoader.LoadingProgress = 0; LoadingSceneController.Instance.ShowLoadingScene(true); #if TESTFAST string nameScene = "LoginScene"; SceneManager.UnloadSceneAsync(nameScene); isDoneNPCRender = true; isDoneWorldRender = true; actLoadChar?.Invoke(); UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete); #else string nameScene = "NPCRender"; UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) => { isDoneNPCRender = value; actLoadChar?.Invoke(); }); nameScene = "a61"; UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) => { isDoneWorldRender = value; actLoadChar?.Invoke(); UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete); }); #endif }, null); } private async void OnEnterWorldComplete() { await Task.Delay(2000); // Request all known packages: 0=Inventory,1=Equipment,2=Task UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2); await Task.Delay(1000); UnityGameSession.RequestCheckSecurityPassWd(""); await Task.Delay(1000); } //private void OnInventoryReceived(List inventoryData) //{ // _inventoryUI.DisplayInventory(inventoryData); //} #if UNITY_EDITOR private void OnValidate() { if (_usernameInputField == null) { // find childrend with name "username" _usernameInputField = transform.Find("username").GetComponent(); } if (_passwordInputField == null) { // find childrend with name "password" _passwordInputField = transform.Find("password").GetComponent(); } if (_loginButton == null) { // find childrend with name "LoginBtn" _loginButton = transform.Find("LoginBtn").GetComponent