101 lines
3.9 KiB
C#
101 lines
3.9 KiB
C#
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using CSNetwork;
|
||
|
||
namespace BrewMonster.Scripts.Chat
|
||
{
|
||
/// <summary>
|
||
/// Chat 输入/协议:wire(MarshalEditBoxText)↔ TMP <sprite> 显示。
|
||
/// Chat input/protocol: wire (MarshalEditBoxText) ↔ TMP <sprite> display.
|
||
/// </summary>
|
||
public static class ChatWireTmpCodec
|
||
{
|
||
private static readonly Regex SpriteTagRegex = new Regex(@"<sprite\s[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||
|
||
/// <summary>
|
||
/// 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.
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// TMP 正文(无频道前缀)→ wire marshal(用于发送)。
|
||
/// TMP body text (no channel prefix) → marshaled wire (for sending).
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Khớp tag với EmotionTMPTagBuilder — duyệt (set,index) đủ nhỏ.
|
||
/// Match tag to EmotionTMPTagBuilder output — brute-force over (set,index) within reasonable bounds.
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Wire → TMP 富文本(FilterEmotionSet + Unmarshal + ConvertInlineItemsToTmp)。
|
||
/// Wire → TMP rich text (FilterEmotionSet + Unmarshal + ConvertInlineItemsToTmp).
|
||
/// </summary>
|
||
public static string WireBodyToTmpForDisplay(string wireBody, IEmotionSpriteMap map, int cEmotion)
|
||
{
|
||
return ChatEmotionDisplayPipeline.ConvertWireBodyToTmpDisplay(wireBody, map, cEmotion);
|
||
}
|
||
}
|
||
}
|