using System.Text; using System.Text.RegularExpressions; using CSNetwork; namespace BrewMonster.Scripts.Chat { /// /// Chat 输入/协议:wire(MarshalEditBoxText)↔ TMP <sprite> 显示。 /// Chat input/protocol: wire (MarshalEditBoxText) ↔ TMP <sprite> display. /// public static class ChatWireTmpCodec { private static readonly Regex SpriteTagRegex = new Regex(@"]*>", RegexOptions.IgnoreCase | RegexOptions.Compiled); /// /// Tạo một đoạn wire marshal cho một emotion (set:index) — gửi server đúng protocol. /// Build one marshaled wire segment for a single emotion (set:index) — correct server protocol. /// public static string BuildMarshaledEmotionWire(int emotionSet, int emotionIndex) { var item = new EditBoxItemBase(AUICommon.EditboxItemType.enumEIEmotion); item.SetName("W"); item.SetInfo(AUICommon.MarshalEmotionInfo(emotionSet, emotionIndex)); var items = new EditBoxItemsSet(); char c = items.AppendItem(item); if (c == '\0') return ""; string display = c.ToString(); return AUICommon.MarshalEditBoxText(display, items); } /// /// TMP 正文(无频道前缀)→ wire marshal(用于发送)。 /// TMP body text (no channel prefix) → marshaled wire (for sending). /// public static string TmpBodyToWire(string tmpBody, IEmotionSpriteMap map) { if (string.IsNullOrEmpty(tmpBody)) return ""; if (map == null) return tmpBody; var sb = new StringBuilder(tmpBody.Length); int last = 0; foreach (Match m in SpriteTagRegex.Matches(tmpBody)) { sb.Append(tmpBody, last, m.Index - last); string tag = m.Value; if (TryMatchSpriteTagToEmotion(map, tag, out int es, out int ei)) sb.Append(BuildMarshaledEmotionWire(es, ei)); else sb.Append(tag); last = m.Index + m.Length; } sb.Append(tmpBody, last, tmpBody.Length - last); return sb.ToString(); } /// /// Khớp tag với EmotionTMPTagBuilder — duyệt (set,index) đủ nhỏ. /// Match tag to EmotionTMPTagBuilder output — brute-force over (set,index) within reasonable bounds. /// public static bool TryMatchSpriteTagToEmotion(IEmotionSpriteMap map, string spriteTag, out int emotionSet, out int emotionIndex) { emotionSet = 0; emotionIndex = 0; if (map == null || string.IsNullOrEmpty(spriteTag)) return false; string normalized = spriteTag.Trim(); for (int s = 0; s < AUICommon.AUIMANAGER_MAX_EMOTIONGROUPS; s++) { for (int e = 0; e < 512; e++) { if (!EmotionTMPTagBuilder.TryBuildEmotionTag(map, s, e, out string built)) continue; if (built == normalized) { emotionSet = s; emotionIndex = e; return true; } } } return false; } /// /// Wire → TMP 富文本(FilterEmotionSet + Unmarshal + ConvertInlineItemsToTmp)。 /// Wire → TMP rich text (FilterEmotionSet + Unmarshal + ConvertInlineItemsToTmp). /// public static string WireBodyToTmpForDisplay(string wireBody, IEmotionSpriteMap map, int cEmotion) { return ChatEmotionDisplayPipeline.ConvertWireBodyToTmpDisplay(wireBody, map, cEmotion); } } }