using System; using System.Text; using BrewMonster.Network; using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; using TMPro; using UnityEngine; using UnityEngine.UI; using BrewMonster.Scripts; using BrewMonster.PerfectWorld.Scripts.Utility.ChatFilter; namespace BrewMonster.UI { /// /// UI screen for creating a new character. /// Equivalent to CDlgCreateGenderName + CDlgCreateProfession in C++. /// public class CreateCharacterScreen : MonoBehaviour { [SerializeField] private GameObject professionSelectionPanel; [SerializeField] private Button[] professionButtons; [SerializeField] private Button maleGenderButton; [SerializeField] private Button femaleGenderButton; [SerializeField] private TMP_InputField nameInputField; [SerializeField] private TMP_Text validationMessageText; [SerializeField] private Button confirmButton; [SerializeField] private Button cancelButton; [SerializeField] private Button backButton; [SerializeField] private CDlgMessageBox messageBoxPrefab; private CDlgMessageBox _messageBoxInstance; private int _currentProfession = -1; private int _currentGender = -1; private Action _onCreateComplete; private Action _onCancel; // Static array matching s_bShowMale[NUM_PROFESSION] from original C++ code (EC_ProfConfigs.cpp) // true = show male, false = show female private static readonly bool[] s_bShowMale = new bool[] { true, // 0: kiem khach (nhan toc) false, // 1: phap su (nhan toc) false, // 2: vu su (tich toc) false, // 3: tien thu (thu toc) true, // 4: than thu (thu toc) true, // 5: thich khach (tich toc) true, // 6: vu mang (vu toc) false, // 7: vu linh (vu toc) true, // 8: kiem linh (linh toc) false, // 9: mi linh (linh toc) true, // 10: da anh (long toc) false, // 11: nguyet tien (long toc) }; private void Start() { if (confirmButton != null) confirmButton.onClick.AddListener(OnConfirmClicked); if (cancelButton != null) cancelButton.onClick.AddListener(OnCancelClicked); if (backButton != null) backButton.onClick.AddListener(OnCancelClicked); if (maleGenderButton != null) maleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_MALE)); if (femaleGenderButton != null) femaleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_FEMALE)); // Setup profession buttons if (professionButtons != null) { for (int i = 0; i < professionButtons.Length && i < 12; i++) { int prof = i; // Capture for closure if (professionButtons[i] != null) professionButtons[i].onClick.AddListener(() => OnProfessionSelected(prof)); } } if (nameInputField != null) { nameInputField.onSubmit.AddListener((text) => { if (CanConfirm()) OnConfirmClicked(); }); nameInputField.onValueChanged.AddListener((text) => ClearValidationError()); } } public void Show(Action onCreateComplete, Action onCancel) { _onCreateComplete = onCreateComplete; _onCancel = onCancel; _currentProfession = -1; _currentGender = -1; gameObject.SetActive(true); if (nameInputField != null) { nameInputField.text = ""; nameInputField.Select(); } ClearValidationError(); UpdateConfirmButtonState(); } public void Hide() { gameObject.SetActive(false); } private void OnProfessionSelected(int profession) { if (profession < 0 || profession >= (int)Profession.NUM_PROFESSION) return; _currentProfession = profession; // Update UI to show selected profession if (professionButtons != null) { for (int i = 0; i < professionButtons.Length; i++) { if (professionButtons[i] != null) { // Visual feedback for selected profession var colors = professionButtons[i].colors; colors.normalColor = (i == profession) ? Color.yellow : Color.white; professionButtons[i].colors = colors; } } } // Auto-select gender based on profession (matching original C++ logic from EC_ProfConfigs.cpp) // This matches the s_bShowMale array in CanShowOnCreate function int autoGender = GetDefaultGenderForProfession(profession); OnGenderSelected(autoGender); UpdateConfirmButtonState(); } /// /// Gets the default gender for a profession based on the original C++ logic. /// Matches the s_bShowMale array from EC_ProfConfigs.cpp CanShowOnCreate function. /// private int GetDefaultGenderForProfession(int profession) { if (profession >= 0 && profession < s_bShowMale.Length) { return s_bShowMale[profession] ? GENDER.GENDER_MALE : GENDER.GENDER_FEMALE; } // Fallback to male if profession is invalid return GENDER.GENDER_MALE; } private void OnGenderSelected(int gender) { if (gender != GENDER.GENDER_MALE && gender != GENDER.GENDER_FEMALE) return; _currentGender = gender; // Update UI to show selected gender if (maleGenderButton != null) { var colors = maleGenderButton.colors; colors.normalColor = (gender == GENDER.GENDER_MALE) ? Color.yellow : Color.white; maleGenderButton.colors = colors; } if (femaleGenderButton != null) { var colors = femaleGenderButton.colors; colors.normalColor = (gender == GENDER.GENDER_FEMALE) ? Color.yellow : Color.white; femaleGenderButton.colors = colors; } UpdateConfirmButtonState(); } private void OnConfirmClicked() { if (!CanConfirm()) return; if (!TryGetValidatedCharacterName(out string characterName)) { return; } // Create RoleInfo using helper method RoleInfo roleInfo = GameSession.CreateNewRoleInfo(characterName, _currentProfession, _currentGender); // Create role via network Debug.Log($"Calling CreateRoleAsync for character: {characterName}, profession: {_currentProfession}, gender: {_currentGender}"); UnityGameSession.CreateRoleAsync(roleInfo, new Octets(), (createdRole) => { if (createdRole != null) { Debug.Log($"Character created successfully: {characterName}, RoleID: {createdRole.roleid}"); Hide(); _onCreateComplete?.Invoke(createdRole); } else { Debug.LogError($"Failed to create character: {characterName}. Check GameSession logs for error details."); // TODO: Show error message to user } }); } private void OnCancelClicked() { Hide(); _onCancel?.Invoke(); } private bool TryGetValidatedCharacterName(out string characterName) { characterName = nameInputField != null ? nameInputField.text.Trim() : string.Empty; if (string.IsNullOrWhiteSpace(characterName)) { ShowValidationError("Character name cannot be empty."); return false; } if (ChatFilterService.ContainsBadWord(characterName)) { ShowValidationError("Character name contains inappropriate words."); return false; } ClearValidationError(); return true; } private void ShowValidationError(string message) { if (validationMessageText != null) { validationMessageText.text = message; validationMessageText.gameObject.SetActive(true); } var dialog = GetOrCreateMessageBoxInstance(); if (dialog != null) { dialog.ShowMessageBoxYes("Invalid Character Name", message, null, null); } else { CECUIManager.Instance?.ShowMessageBoxYes("Invalid Character Name", message, null, null); } Debug.LogWarning(message); } private CDlgMessageBox GetOrCreateMessageBoxInstance() { if (_messageBoxInstance != null) { return _messageBoxInstance; } if (messageBoxPrefab == null) { return null; } var canvas = GetComponentInParent(); if (canvas == null) { return null; } _messageBoxInstance = Instantiate(messageBoxPrefab, canvas.transform); _messageBoxInstance.gameObject.SetActive(false); return _messageBoxInstance; } private void ClearValidationError() { if (validationMessageText != null) { validationMessageText.text = string.Empty; validationMessageText.gameObject.SetActive(false); } } private bool CanConfirm() { if (_currentProfession < 0 || _currentProfession >= (int)Profession.NUM_PROFESSION) return false; if (_currentGender != GENDER.GENDER_MALE && _currentGender != GENDER.GENDER_FEMALE) return false; string name = nameInputField != null ? nameInputField.text : ""; if (string.IsNullOrWhiteSpace(name)) return false; return true; } private void UpdateConfirmButtonState() { if (confirmButton != null) { confirmButton.interactable = CanConfirm(); } } private void Update() { // Update confirm button state in case name changes if (nameInputField != null && nameInputField.isFocused) { UpdateConfirmButtonState(); } } } }