using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; namespace BrewMonster.UI { public class AUIManager { protected DialogScriptTableObject m_dialogResouce; protected Canvas m_canvas; protected Dictionary m_StringTable = new Dictionary(); protected Dictionary m_auiDialog_stringTable = new Dictionary(); public Dictionary m_DlgName = new Dictionary(); public string GetStringFromTable(int idString) { if (m_StringTable.TryGetValue(idString, out var str)) return str; return null; } public string GetStringFromAuiDialogTable(int idString) { if (m_auiDialog_stringTable.TryGetValue(idString, out var str)) return str; return null; } public void SetDependency(DialogScriptTableObject resouce, Canvas canvas) { m_dialogResouce = resouce; m_canvas = canvas; } public virtual void Init() { ImportStringTable("Assets/Addressable/ingame.txt"); ImportAuiDialogStringTable("Assets/Addressable/msgbox.txt"); } public string Translate(ushort[] str) { if (str == null || str.Length == 0) return null; string m_AWString = ""; string input = new string(str.Where(c => c != 0).Select(c => (char)c).ToArray()); m_AWString = input; var result = new System.Text.StringBuilder(); int i = 0; while (i < input.Length) { char c = input[i]; if (c != '\\') { result.Append(c); i++; continue; } i++; if (i >= input.Length) break; char next = input[i]; switch (next) { case '\n': i++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int value = 0; int count = 3; while (i < input.Length && input[i] >= '0' && input[i] <= '7' && count > 0) { count--; value = value * 8 + (input[i] - '0'); i++; } if (value <= 255) result.Append((char)(value & 0xFF)); break; } case '"': case '\'': case '\\': result.Append(next); i++; break; case 'n': result.Append('\n'); i++; break; case 'r': result.Append('\r'); i++; break; case 't': result.Append('\t'); i++; break; case 'v': result.Append('\v'); i++; break; default: i++; break; } } m_AWString = result.ToString(); return m_AWString; } public bool ImportStringTable(string pszFilename) { //AWScriptFile s = new AWScriptFile(); var ta = LoadStringTableTextAssetByAddressables(pszFilename); if (ta == null || string.IsNullOrEmpty(ta.text)) { BMLogger.LogError($"[AUIManager] ImportStringTable failed: cannot load Addressables TextAsset for key='{pszFilename}'"); return false; } using (var sr = new StringReader(ta.text)) { string line; while ((line = sr.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) continue; var parts = line.Split('\t', StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 2) continue; if (int.TryParse(parts[0], out int key)) { string value = parts[1].Trim(); if (value.StartsWith("\"") && value.EndsWith("\"")) value = value.Substring(1, value.Length - 2); m_StringTable[key] = value; } } } return true; //bool bval = s.Open(szFilename); //if (!bval) return false; //while (!s.IsEnd()) //{ // bval = s.GetNextToken(true); // if (!bval) break; // End of file. // int idString = int.Parse(ByteToStringUtils.UshortArrayToUnicodeString(s.m_szToken)); // bval = s.GetNextToken(true); // if (!bval) return false; // string str = (Translate(s.m_szToken)); // m_StringTable[idString] = str; //} //s.Close(); //if (a_stricmp(GetStringFromTable(1), _AL("")) == 0) //1 Ĭ������ // m_StringTable[1] = _AL("����ϸ��һ����"); //m_strDefaultFontName = GetStringFromTable(1); //if (a_stricmp(GetStringFromTable(2), _AL("")) == 0) //2 Ĭ�������С // m_StringTable[2] = _AL("10"); //m_nDefaultFontSize = a_atoi(GetStringFromTable(2)); //if (a_stricmp(GetStringFromTable(3), _AL("")) == 0) //3 ���� '\t' �൱�ڶ��ٸ� 'W'�Ŀ��� // m_StringTable[3] = _AL("30"); //_tab_char = a_atoi(GetStringFromTable(3)); //if (a_stricmp(GetStringFromTable(4), _AL("")) == 0) //4 m_FontImagePicture �����С // m_StringTable[4] = m_StringTable[2]; //if (a_stricmp(GetStringFromTable(5), _AL("")) == 0) //5 MessageBox �����С // m_StringTable[5] = m_StringTable[2]; //if (a_stricmp(GetStringFromTable(6), _AL("")) == 0) //6 MessageBox shadow // m_StringTable[6] = _AL("0"); //if (a_stricmp(GetStringFromTable(7), _AL("")) == 0) //7 MessageBox outline // m_StringTable[7] = _AL("0"); //if (a_stricmp(GetStringFromTable(8), _AL("")) == 0) //8 MessageBox outline color // m_StringTable[8] = _AL("0"); //m_FontHint.szFontName = GetStringFromTable(1); //m_FontHint.nFontSize = a_atoi(GetStringFromTable(2)); //m_FontImagePicture.szFontName = GetStringFromTable(1); //m_FontImagePicture.nFontSize = a_atoi(GetStringFromTable(4)); //m_FontImagePicture.nOutline = 1; //m_FontMessageBox.szFontName = GetStringFromTable(1); //m_FontMessageBox.nFontSize = a_atoi(GetStringFromTable(5)); //m_FontMessageBox.nShadow = a_atoi(GetStringFromTable(6)); //m_FontMessageBox.nOutline = a_atoi(GetStringFromTable(7)); //return true; } public bool ImportAuiDialogStringTable(string pszFilename) { //bool bval; //int idString; //string str; //AWScriptFile s = new AWScriptFile(); var ta = LoadStringTableTextAssetByAddressables(pszFilename); if (ta == null || string.IsNullOrEmpty(ta.text)) { BMLogger.LogError($"[AUIManager] ImportAuiDialogStringTable failed: cannot load Addressables TextAsset for key='{pszFilename}'"); return false; } //bval = s.Open(szFilename); //if (!bval) return true; // Ignore error. //while (!s.IsEnd()) //{ // bval = s.GetNextToken(true); // if (!bval) break; // End of file. // idString = int.Parse(ByteToStringUtils.UshortArrayToUnicodeString(s.m_szToken)); // bval = s.GetNextToken(true); // if (!bval) return false; // str = ByteToStringUtils.UshortArrayToUnicodeString(s.m_szToken); // if(m_auiDialog_stringTable.TryGetValue(idString, out string value)) // { // m_auiDialog_stringTable[idString] = str; // } // else // { // m_auiDialog_stringTable.Add(idString, str); // } //} //s.Close(); using (var sr = new StringReader(ta.text)) { string line; while ((line = sr.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) continue; var parts = line.Split('\t', StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 2) continue; if (int.TryParse(parts[0], out int key)) { string value = parts[1].Trim(); if (value.StartsWith("\"") && value.EndsWith("\"")) value = value.Substring(1, value.Length - 2); m_auiDialog_stringTable[key] = value; } } } return true; } private static TextAsset LoadStringTableTextAssetByAddressables(string key) { try { // Initialize Addressables if not already initialized (Unity-safe) Addressables.InitializeAsync().WaitForCompletion(); // Load using Addressables directly with WaitForCompletion (Unity-safe, won't deadlock) // This matches the pattern used in EC_Game.cs var handle = Addressables.LoadAssetAsync(key); var textAsset = handle.WaitForCompletion(); if (handle.Status == AsyncOperationStatus.Succeeded && textAsset != null) { // Keep the handle valid; string tables are used for the whole session // Note: We don't release the handle here to keep the asset loaded return textAsset; } if (handle.IsValid()) { Addressables.Release(handle); } BMLogger.LogError($"[AUIManager] Failed to load TextAsset for key='{key}'"); return null; } catch (Exception e) { BMLogger.LogError($"[AUIManager] LoadStringTableTextAssetByAddressables exception for key='{key}': {e}"); return null; } } public AUIDialog GetDialog(string pszName) { if(m_DlgName.TryGetValue(pszName, out AUIDialog dlg)) { return dlg; } else { var prefab = m_dialogResouce.GetPrefabDialog(pszName); if(prefab != null) { var instance = GameObject.Instantiate(prefab, m_canvas.transform); var dialog = instance.GetComponent(); if (dialog != null) { dialog.SetAUIManager(this); m_DlgName[pszName] = dialog; return dialog; } } else { BMLogger.LogError($" Không tìm thấy prefab chứa dialog {pszName} "); } } return null; } } }