using System; using System.Collections.Generic; using System.Linq; using System.Text; using CSNetwork; namespace CSNetwork { public static class AUICommon { public const char AUICOMMON_ITEM_CODE_START = (char)0xE000; public const char AUICOMMON_ITEM_CODE_END = (char)0xE3FF; public const int AUIMANAGER_MAX_EMOTIONGROUPS = 32; public const int MAX_EDITBOX_ITEM_NUM = AUICOMMON_ITEM_CODE_END - AUICOMMON_ITEM_CODE_START + 1; public const int MAXNUM_CUSTOM_ITEM = 255; public enum EditboxItemType { enumEIEmotion = 0, enumEIIvtrlItem, enumEICoord, enumEIImage, enumEIScriptItem, enumEICustom, enumEINum = enumEICustom + MAXNUM_CUSTOM_ITEM } public static void AUI_ConvertChatString(ref string pszChat, ref char[] pszConv, bool bName) { if (string.IsNullOrEmpty(pszChat) || pszConv == null) return; int nLen = 0; for (int i = 0; i < pszChat.Length; i++) { char c = pszChat[i]; if (c == '^') { if (nLen + 1 < pszConv.Length) { pszConv[nLen] = '^'; pszConv[nLen + 1] = '^'; nLen += 2; } } else if (c == '&') { if (nLen + 1 < pszConv.Length) { pszConv[nLen] = '^'; pszConv[nLen + 1] = '&'; nLen += 2; } } else { if (nLen < pszConv.Length) { pszConv[nLen] = c; nLen++; } } } // kết thúc chuỗi bằng ký tự null if (nLen < pszConv.Length) pszConv[nLen] = '\0'; } public static string FilterEmotionSet(string szText, int nEmotionSet) { EditBoxItemsSet itemsSet = new EditBoxItemsSet(); string strOrgText = UnmarshalEditBoxText(szText, itemsSet); int nCount = itemsSet.GetItemCount(); if (nCount == 0) return szText; var it = itemsSet.GetItemIterator(); for (int i = 0; i < nCount; i++) { EditBoxItemBase pItem = it.Current.Value; if (pItem.GetType() == EditboxItemType.enumEIEmotion) { int nSet = 0; int nIndex = 0; UnmarshalEmotionInfo(pItem.GetInfo(), ref nSet, ref nIndex); pItem.SetInfo(MarshalEmotionInfo(nEmotionSet, nIndex)); } it.MoveNext(); } return MarshalEditBoxText(strOrgText, itemsSet); } public static string MarshalEmotionInfo(int nEmotionSet, int nIndex) { return nEmotionSet.ToString() + ":" + nIndex.ToString(); } public static void UnmarshalEmotionInfo(string szText, ref int nEmotionSet, ref int nIndex) { if (string.IsNullOrEmpty(szText)) return; var parts = szText.Split(':'); if (parts.Length >= 2) { int.TryParse(parts[0], out nEmotionSet); int.TryParse(parts[1], out nIndex); } // a_ClampFloor(nEmotionSet, 0); if (nEmotionSet < 0) nEmotionSet = 0; // a_ClampFloor(nIndex, 0); if (nIndex < 0) nIndex = 0; if (nEmotionSet >= AUIMANAGER_MAX_EMOTIONGROUPS) nEmotionSet = 0; } public static string MarshalEditBoxText(string text, EditBoxItemsSet itemsSet) { var sb = new StringBuilder(text.Length * 2); int start = 0; for (int i = 0; i < text.Length; i++) { char ch = text[i]; if (IsEditboxItemCode(ch)) { sb.Append(text, start, i - start + 1); var item = itemsSet.GetItemByChar(ch); if (item != null) sb.Append(item.Serialize()); start = i + 1; } } if (start < text.Length) sb.Append(text, start, text.Length - start); return sb.ToString(); } public static bool IsEditboxItemCode(char ch) { return ch >= AUICOMMON_ITEM_CODE_START && ch <= AUICOMMON_ITEM_CODE_END; } public static string UnmarshalEditBoxText(string szText, EditBoxItemsSet itemsSet) { return UnmarshalEditBoxText( szText, itemsSet, 0, null, 0, 0, null, 0, false, false, 0 ); } public static string UnmarshalEditBoxText( string? sztext, EditBoxItemsSet itemsSet, int msgIndex, string ivtrItem, uint clIvtrItem, int itemMask, EditboxScriptItem[]? scriptItems, int scriptItemCount, bool underLine, bool sameColor, uint clUnderLine) { if (sztext == null) return ""; var scriptInfo = new AUI_UNMARSH_SCRIPTITEM_INFO { ScriptItems = scriptItems, ScriptItemCount = scriptItemCount }; var underlineInfo = new AUI_UNMARSH_UNDERLINE_INFO { UnderLine = underLine, SameColor = sameColor, UnderLineColor = clUnderLine }; return UnmarshalEditBoxTextEx( sztext, itemsSet, msgIndex, ivtrItem, clIvtrItem, itemMask, scriptInfo, underlineInfo ); } public static string UnmarshalEditBoxTextEx( string text, EditBoxItemsSet itemsSet, int msgIndex, string ivtrItem, uint clIvtrItem, int itemMask, AUI_UNMARSH_SCRIPTITEM_INFO? scriptInfo, AUI_UNMARSH_UNDERLINE_INFO? underlineInfo) { if (text == null) return ""; int start = 0; int i = 0; int curScriptIndex = 0; var sb = new StringBuilder(); while (i < text.Length) { char ch = text[i]; if (IsEditboxItemCode(ch)) { if (i > start) sb.Append(text, start, i - start); i++; EditBoxItemBase? item = EditBoxItemBase.Unserialize(text, ref i); start = i; if (item != null) { if ((itemMask & (1 << (int)item.GetType())) != 0) { char newChar = itemsSet.AppendItem(item); if (newChar != '\0') { sb.Append(newChar); item.SetMsgIndex(msgIndex); if (underlineInfo != null) { item.SetUnderLine( underlineInfo.UnderLine, underlineInfo.SameColor, underlineInfo.UnderLineColor); } switch (item.GetType()) { case EditboxItemType.enumEIIvtrlItem: item.SetName(ivtrItem); item.SetColor(clIvtrItem); break; case EditboxItemType.enumEIScriptItem: if (scriptInfo != null && curScriptIndex < scriptInfo.ScriptItemCount) { var sItem = scriptInfo.ScriptItems![curScriptIndex]; item.SetName(sItem.Name); item.SetColor(sItem.Color); var data = sItem.Name; if (data != null) item.SetExtraData(sItem.Data, sItem.GetDataSize()); curScriptIndex++; } break; } } } } } else { i++; } } if (i > start) sb.Append(text, start, i - start); return sb.ToString(); } /// /// Chuyển đổi định dạng printf (C-style: %s, %d) sang string.Format (C#-style: {0}, {1}) /// public static string ConvertPrintfToCSharpFormat(string format) { if (string.IsNullOrEmpty(format)) return ""; StringBuilder sb = new StringBuilder(); int argIndex = 0; for (int i = 0; i < format.Length; i++) { if (format[i] == '%' && i + 1 < format.Length) { char next = format[i + 1]; if (next == '%') // Trường hợp %% -> % { sb.Append('%'); i++; } else { sb.Append('{').Append(argIndex++).Append('}'); i++; // Nhảy qua các ký tự định dạng (ví dụ: %02d, %ls, %f) while (i < format.Length && (char.IsDigit(format[i]) || format[i] == '.' || format[i] == 'l' || format[i] == 'u' || format[i] == 'd' || format[i] == 's' || format[i] == 'f' || format[i] == 'x')) { // Nếu gặp ký tự kết thúc định dạng (s, d, f, ...) thì dừng lại sau ký tự đó char c = format[i]; if (c == 's' || c == 'd' || c == 'f' || c == 'u' || c == 'x' || c == 'g') { // i++; // Đã ở đúng vị trí để vòng lặp cha thực hiện i++ tiếp theo break; } i++; } } } else { sb.Append(format[i]); } } return sb.ToString(); } } } public class AUI_UNMARSH_SCRIPTITEM_INFO { public EditboxScriptItem[]? ScriptItems; public int ScriptItemCount; } public class AUI_UNMARSH_UNDERLINE_INFO { public bool UnderLine; public bool SameColor; public uint UnderLineColor; } public class EditBoxItemsSet { const char AUICOMMON_ITEM_CODE_START = '\u0001'; const char AUICOMMON_ITEM_CODE_END = '\u0010'; protected Dictionary m_Items = new(); protected int[] m_ItemsCount = new int[(int)AUICommon.EditboxItemType.enumEINum]; protected char m_cNextItemChar; public EditBoxItemsSet() { Array.Clear(m_ItemsCount, 0, m_ItemsCount.Length); m_cNextItemChar = AUICommon.AUICOMMON_ITEM_CODE_START; } public EditBoxItemsSet(EditBoxItemsSet itemsset) { this.Assign(itemsset); } public void Assign(EditBoxItemsSet src) { m_Items.Clear(); foreach (var kv in src.m_Items) { m_Items[kv.Key] = new EditBoxItemBase(kv.Value); } Array.Copy(src.m_ItemsCount, m_ItemsCount, m_ItemsCount.Length); m_cNextItemChar = src.m_cNextItemChar; } public void Release() { m_Items.Clear(); Array.Clear(m_ItemsCount, 0, m_ItemsCount.Length); m_cNextItemChar = AUICommon.AUICOMMON_ITEM_CODE_START; } public int GetItemCount() { return m_Items.Count; } public Dictionary.Enumerator GetItemIterator() { return m_Items.GetEnumerator(); } public EditBoxItemBase? GetItemByChar(char ch) { if (!IsEditboxItemCode(ch)) throw new Exception("Invalid editbox item char"); if (m_Items.TryGetValue(ch, out var item)) return item; return null; } public bool IsEditboxItemCode(char ch) { return ch >= AUICOMMON_ITEM_CODE_START && ch <= AUICOMMON_ITEM_CODE_END; } public int GetItemCountByType(AUICommon.EditboxItemType type) { return m_ItemsCount[(int)type]; } public void DelItemByChar(char ch) { if (m_Items.TryGetValue(ch, out var item)) { m_ItemsCount[(int)item.GetType()]--; m_Items.Remove(ch); } } public char AppendItem(EditBoxItemBase pItem) { if (m_Items.Count >= AUICommon.MAX_EDITBOX_ITEM_NUM) return '\0'; char cur = m_cNextItemChar; do { if (m_Items.ContainsKey(m_cNextItemChar)) { m_cNextItemChar = EditboxGetNextChar(m_cNextItemChar); } else { m_Items[m_cNextItemChar] = pItem; m_ItemsCount[(int)pItem.GetType()]++; char ret = m_cNextItemChar; m_cNextItemChar = EditboxGetNextChar(m_cNextItemChar); return ret; } } while (m_cNextItemChar != cur); return '\0'; } public char EditboxGetNextChar(char cur) { if (cur >= AUICOMMON_ITEM_CODE_END) return AUICOMMON_ITEM_CODE_START; else return (char)(cur + 1); } public char AppendItem(AUICommon.EditboxItemType type, uint cl, string szName, string szInfo) { // Implement theo logic C++ gốc throw new NotImplementedException(); } public int GetTotalExtraDataSize() { int sz = 0; foreach (var item in m_Items.Values) { sz += item.GetExtraDataSize(); } return sz; } } public class EditBoxItemBase { protected AUICommon.EditboxItemType m_type; protected uint m_dwColor; protected string m_strName = ""; protected string m_strInfo = ""; protected int m_nMsgIndex; protected int m_nImageIndex; protected int m_nImageFrame; protected float m_fImageScale; protected byte[]? m_pExtraData; protected int m_uExtraDataSize; protected bool m_bUnderLine; protected bool m_bSameColor; protected uint m_dwUnderLineColor; protected static EditBoxItemBase?[] m_mapCustomType = new EditBoxItemBase[AUICommon.MAXNUM_CUSTOM_ITEM]; public EditBoxItemBase(AUICommon.EditboxItemType type) { m_type = type; m_dwColor = 0xffffffff; m_nMsgIndex = 0; m_nImageIndex = 0; m_nImageFrame = 0; m_fImageScale = 1.0f; m_bUnderLine = false; m_bSameColor = true; m_dwUnderLineColor = 0; RegisterCustomType(type); } public EditBoxItemBase(EditBoxItemBase src) { Assign(src); } public bool UnserializeContent(string text, ref int index) { int szNext; int szEnd = text.IndexOf("<", index); if (szEnd == -1) return false; if (m_type == AUICommon.EditboxItemType.enumEICoord) { szNext = szEnd + 1; if (!TryParseInt(text, szNext, out int color)) return false; SetColor((uint)color); szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szNext = szEnd + 2; if (!TryParseInt(text, szNext, out int underline)) return false; m_bUnderLine = underline != 0; szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szNext = szEnd + 2; if (!TryParseInt(text, szNext, out int underlineColor)) return false; m_dwUnderLineColor = (uint)underlineColor; szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; m_bSameColor = (m_dwUnderLineColor == m_dwColor); szNext = szEnd + 2; szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; SetName(text.Substring(szNext, szEnd - szNext)); szEnd += 1; } else if (m_type == AUICommon.EditboxItemType.enumEIImage) { szNext = szEnd + 1; if (!TryParseUInt(text, szNext, out uint color)) return false; SetColor(color); szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szNext = szEnd + 2; if (!TryParseInt(text, szNext, out int imageIndex)) return false; SetImageIndex(imageIndex); szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szNext = szEnd + 2; if (!TryParseInt(text, szNext, out int frame)) return false; SetImageFrame(frame); szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szNext = szEnd + 2; if (!float.TryParse(text.Substring(szNext), out float f)) return false; SetImageScale(f); szEnd = text.IndexOf("><", szNext); if (szEnd == -1) return false; szEnd += 1; } else if (m_type == AUICommon.EditboxItemType.enumEIEmotion) { SetName("W"); } szNext = szEnd + 1; szEnd = text.IndexOf('>', szNext); if (szEnd == -1) return false; SetInfo(text.Substring(szNext, szEnd - szNext)); index = szEnd + 1; return true; } private bool TryParseInt(string text, int start, out int value) { int end = start; while (end < text.Length && char.IsDigit(text[end])) end++; return int.TryParse(text.Substring(start, end - start), out value); } private bool TryParseUInt(string text, int start, out uint value) { int end = start; while (end < text.Length && char.IsDigit(text[end])) end++; return uint.TryParse(text.Substring(start, end - start), out value); } protected void RegisterCustomType(AUICommon.EditboxItemType type) { if (type >= AUICommon.EditboxItemType.enumEICustom && type < AUICommon.EditboxItemType.enumEINum) { int index = (int)type - (int)AUICommon.EditboxItemType.enumEICustom; if (m_mapCustomType[index] == null) m_mapCustomType[index] = this; } } protected virtual EditBoxItemBase Create() { return new EditBoxItemBase(m_type); } protected static EditBoxItemBase? GetCustomItemFromType(AUICommon.EditboxItemType type) { if (type >= AUICommon.EditboxItemType.enumEICustom && type < AUICommon.EditboxItemType.enumEINum) { return m_mapCustomType[(int)type - (int)AUICommon.EditboxItemType.enumEICustom]; } return null; } public uint GetColor() => m_dwColor; public AUICommon.EditboxItemType GetType() => m_type; public string GetName() => m_strName; public string GetInfo() => m_strInfo; public int GetMsgIndex() => m_nMsgIndex; public int GetImageIndex() => m_nImageIndex; public int GetImageFrame() => m_nImageFrame; public float GetImageScale() => m_fImageScale; public bool GetUnderLine() => m_bUnderLine; public bool GetSameColor() => m_bSameColor; public uint GetUnderLineColor() => m_dwUnderLineColor; public void SetColor(uint cl) => m_dwColor = cl; public void SetName(string name) => m_strName = name; public void SetInfo(string info) => m_strInfo = info; public void SetMsgIndex(int n) => m_nMsgIndex = n; public void SetImageIndex(int n) => m_nImageIndex = n; public void SetImageFrame(int n) => m_nImageFrame = n; public void SetImageScale(float f) => m_fImageScale = f; public byte[]? GetExtraData() => m_pExtraData; public int GetExtraDataSize() => m_uExtraDataSize; public void SetUnderLine(bool underline, bool sameColor = true, uint underlineColor = 0) { m_bUnderLine = underline; m_bSameColor = sameColor; m_dwUnderLineColor = underlineColor; } public void SetExtraData(byte[] data, int size) { m_pExtraData = new byte[size]; Array.Copy(data, 0, m_pExtraData, 0, size); m_uExtraDataSize = size; } public virtual string Serialize() { return ""; } public static EditBoxItemBase Unserialize(string text, ref int index) { int start = text.IndexOf('<', index); if (start == -1) return null; start++; int endType = text.IndexOf('>', start); if (endType == -1) return null; string typeStr = text.Substring(start, endType - start); if (!int.TryParse(typeStr, out int type)) return null; if (type < 0 || type >= (int)AUICommon.EditboxItemType.enumEINum) return null; index = endType + 1; EditBoxItemBase pItem = EditBoxItemBase.GetCustomItemFromType((AUICommon.EditboxItemType)type); EditBoxItemBase pItemNew; if (pItem == null) { pItemNew = new EditBoxItemBase((AUICommon.EditboxItemType)type); } else { pItemNew = pItem.Create(); } if (!pItemNew.UnserializeContent(text, ref index)) { return null; } return pItemNew; } public void Assign(EditBoxItemBase src) { m_type = src.m_type; m_dwColor = src.m_dwColor; m_strName = src.m_strName; m_strInfo = src.m_strInfo; m_nMsgIndex = src.m_nMsgIndex; m_nImageIndex = src.m_nImageIndex; m_nImageFrame = src.m_nImageFrame; m_fImageScale = src.m_fImageScale; if (src.m_pExtraData != null) { SetExtraData(src.m_pExtraData, src.m_uExtraDataSize); } else { m_pExtraData = null; m_uExtraDataSize = 0; } RegisterCustomType(m_type); } } public class EditboxScriptItem { public string Name { get; set; } = ""; public uint Color { get; set; } public byte[]? Data { get; private set; } public void SetData(byte[] data) { Data = data.ToArray(); // deep copy } public int GetDataSize() { return Data?.Length ?? 0; } }