Compare commits

...

2 Commits

Author SHA1 Message Date
Yue-bin
de679f5dd1 📃 docs: v1.0.2 2025-05-25 02:10:36 +08:00
Yue-bin
1e9616d06d 🐞 fix: 修复了标签处理 2025-05-24 22:56:36 +08:00
4 changed files with 182 additions and 43 deletions

View File

@@ -14,11 +14,19 @@ public class CNText : BaseUnityPlugin
{ {
static ConfigEntry<bool> needReplaceTextComp; static ConfigEntry<bool> needReplaceTextComp;
static ConfigEntry<int> customTextFontSize; static ConfigEntry<int> customTextFontSize;
static ConfigEntry<bool> removeUnsupportedTags;
static ConfigEntry<bool> closeUnclosedTags;
void Awake() void Awake()
{ {
needReplaceTextComp = Config.Bind<bool>("OnlinePlayerUI", "NeedReplaceTextComp", true, "是否显示替换的头顶玩家名称文本组件"); needReplaceTextComp = Config.Bind<bool>("OnlinePlayerUI", "NeedReplaceTextComp", true, "是否显示替换的头顶玩家名称文本组件");
customTextFontSize = Config.Bind<int>("OnlinePlayerUI", "CustomTextFontSize", 38, "替换后头顶玩家名称字号"); customTextFontSize = Config.Bind<int>("OnlinePlayerUI", "CustomTextFontSize", 38, "替换后头顶玩家名称字号");
Harmony.CreateAndPatchAll(typeof(OnlinePlayerUIUpdatePatch)); removeUnsupportedTags = Config.Bind<bool>("OnlinePlayerUI", "RemoveUnsupportedTags", true, "是否移除不支持的标签");
closeUnclosedTags = Config.Bind<bool>("OnlinePlayerUI", "CloseUnclosedTags", true, "是否自动闭合未闭合的标签");
if (needReplaceTextComp.Value)
{
Harmony.CreateAndPatchAll(typeof(OnlinePlayerUIUpdatePatch));
}
} }
static Font LoadCustomFont() static Font LoadCustomFont()
{ {
@@ -44,27 +52,6 @@ public class CNText : BaseUnityPlugin
return font; return font;
} }
static public string ReformatName(string name)
{
name = name.Replace("<#", "</Color><Color=#");
if (name.StartsWith("</Color>"))
{
name = name.Substring(8);
}
if (name.LastIndexOf("</Color>") < name.LastIndexOf("<Color=#"))
{
name += "</Color>";
}
if (name.IndexOf("</Color>") < name.LastIndexOf("<Color=#"))
{
name = name.Substring(0, name.IndexOf("</Color>")) + name.Substring(name.IndexOf("</Color>") + 8);
}
if (name.LastIndexOf("</I>") < name.LastIndexOf("<I>") || name.LastIndexOf("</i>") < name.LastIndexOf("<i>"))
{
name += "</i>";
}
return name;
}
[HarmonyPatch(typeof(OnlinePlayerUI), "Update")] [HarmonyPatch(typeof(OnlinePlayerUI), "Update")]
class OnlinePlayerUIUpdatePatch class OnlinePlayerUIUpdatePatch
{ {
@@ -100,17 +87,9 @@ public class CNText : BaseUnityPlugin
customText.alignment = TextAnchor.MiddleCenter; customText.alignment = TextAnchor.MiddleCenter;
} }
customText.color = tmpPlayerText.color; customText.color = tmpPlayerText.color;
customText.text = ReformatName(tmpPlayerText.text); customText.text = TMPToFontTextConverter.Convert(tmpPlayerText.text, removeUnsupportedTags.Value, closeUnclosedTags.Value);
if (needReplaceTextComp.Value) tmpPlayerText.enabled = false;
{ customText.enabled = true;
tmpPlayerText.enabled = false;
customText.enabled = true;
}
else
{
tmpPlayerText.enabled = true;
customText.enabled = false;
}
customText.supportRichText = true; customText.supportRichText = true;
} }
} }

153
TMPToFontTextConverter.cs Normal file
View File

@@ -0,0 +1,153 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public class TMPToFontTextConverter
{
private static readonly Dictionary<string, string> ColorNameToHex = new Dictionary<string, string>()
{
{"white", "#FFFFFF"}, {"black", "#000000"},
{"red", "#FF0000"}, {"green", "#00FF00"},
{"blue", "#0000FF"}, {"yellow", "#FFFF00"},
{"cyan", "#00FFFF"}, {"magenta", "#FF00FF"},
{"gray", "#808080"}, {"grey", "#808080"}
};
public static string Convert(string input, bool removeUnsupportedTags = true, bool closeUnclosedTags = true)
{
var output = PreprocessColorTags(input);
output = ProcessColorTags(output);
output = RemoveUnsupportedTags(output, removeUnsupportedTags);
return closeUnclosedTags ? CloseUnclosedTags(output) : output;
}
private static string PreprocessColorTags(string input)
{
// 转换简写颜色标签格式(带#和不带#
return Regex.Replace(input, @"<(#?[0-9a-fA-F]{3,8})>", match =>
{
string hex = match.Groups[1].Value;
return $"<color={(hex.StartsWith("#") ? hex : "#" + hex)}>";
});
}
private static string ProcessColorTags(string input)
{
// 匹配所有颜色标签进行标准化处理
return Regex.Replace(input, @"<color=(.*?)>", match =>
{
string colorValue = match.Groups[1].Value.Trim();
// 处理颜色名称
if (ColorNameToHex.TryGetValue(colorValue.ToLower(), out var hex))
return $"<color={hex}>";
// 处理十六进制格式
if (colorValue.StartsWith("#"))
{
string cleanHex = colorValue.Replace("#", "");
return FormatHexColor(cleanHex);
}
// 处理RGBA格式
if (colorValue.StartsWith("rgba"))
return ConvertRGBA(colorValue);
return $"<color={colorValue}>"; // 保留原始格式
}, RegexOptions.IgnoreCase);
}
private static string FormatHexColor(string hex)
{
hex = hex.ToUpper();
switch (hex.Length)
{
case 3: // #RGB → RRGGBB
return $"<color=#{new string(hex[0], 2)}{new string(hex[1], 2)}{new string(hex[2], 2)}>";
case 6: // RRGGBB → RRGGBBFF
return $"<color=#{hex}FF>";
case 8: // RRGGBBAA → 保持原样
return $"<color=#{hex}>";
default: // 无效格式保持原样
return $"<color=#{hex}>";
}
}
private static string RemoveUnsupportedTags(string input, bool removeUnsupported)
{
if (!removeUnsupported) return input;
// 删除不支持的标签及其内容(保留内容)
string[] unsupportedTags = { "font", "s", "u", "align" };
foreach (var tag in unsupportedTags)
{
input = Regex.Replace(input, $@"<{tag}=.*?>", "", RegexOptions.IgnoreCase);
input = Regex.Replace(input, $@"<\/{tag}>", "", RegexOptions.IgnoreCase);
}
return input;
}
private static string CloseUnclosedTags(string input)
{
Stack<string> tagStack = new Stack<string>();
StringBuilder output = new StringBuilder();
int index = 0;
while (index < input.Length)
{
if (input[index] == '<')
{
int tagEnd = input.IndexOf('>', index);
if (tagEnd == -1) break;
string fullTag = input.Substring(index, tagEnd - index + 1);
bool isClosing = fullTag.StartsWith("</");
string tagType = Regex.Match(fullTag, @"</?(\w+)").Groups[1].Value.ToLower();
output.Append(fullTag);
// 处理标签栈
if (!isClosing && !tagType.EndsWith("/"))
{
tagStack.Push(tagType); // 记录基础标签类型
}
else if (isClosing)
{
// 正确匹配最近打开的标签
if (tagStack.Count > 0 && tagStack.Peek() == tagType)
tagStack.Pop();
}
index = tagEnd + 1;
}
else
{
output.Append(input[index++]);
}
}
// 补全剩余标签(保持打开顺序)
while (tagStack.Count > 0)
{
string tag = tagStack.Pop();
output.Append($"</{tag}>");
}
return output.ToString();
}
private static string ConvertRGBA(string rgba)
{
var matches = Regex.Matches(rgba, @"\d+\.?\d*");
if (matches.Count < 3) return "#FFFFFFFF";
StringBuilder hex = new StringBuilder("#");
for (int i = 0; i < 3; i++)
hex.Append((int.Parse(matches[i].Value) * 255).ToString("X2"));
hex.Append(matches.Count > 3 ?
((int)(float.Parse(matches[3].Value) * 255)).ToString("X2") : "FF");
return $"<color={hex}>";
}
}

View File

@@ -27,10 +27,16 @@
└─StreamingAssets └─StreamingAssets
``` ```
**其中 `StreamingAssets`为新增的目录** **其中 `StreamingAssets`为新增的目录**
## 更新日志 ## 更新日志
### v1.0.2
fix:
- 标签解析,重构了标签转换器
### v1.0.1 ### v1.0.1
fix: fix:

View File

@@ -4,7 +4,7 @@
<TargetFramework>net35</TargetFramework> <TargetFramework>net35</TargetFramework>
<AssemblyName>stick.plugins.cntext</AssemblyName> <AssemblyName>stick.plugins.cntext</AssemblyName>
<Product>cntext</Product> <Product>cntext</Product>
<Version>1.0.1</Version> <Version>1.0.2</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources> <RestoreAdditionalProjectSources>
@@ -22,15 +22,16 @@
<PackageReference Include="Mono.Cecil" Version="0.10.4" /> <PackageReference Include="Mono.Cecil" Version="0.10.4" />
<PackageReference Include="UnityEngine.Modules" Version="5.6.3.16509117" IncludeAssets="compile" /> <PackageReference Include="UnityEngine.Modules" Version="5.6.3.16509117" IncludeAssets="compile" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'"> <ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2"
PrivateAssets="all" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>lib/Assembly-CSharp.dll</HintPath> <HintPath>lib/Assembly-CSharp.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -39,16 +40,16 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="UnityEngine.UI"> <Reference Include="UnityEngine.UI">
<HintPath>lib/UnityEngine.UI.dll</HintPath> <HintPath>lib/UnityEngine.UI.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="TextMeshPro"> <Reference Include="TextMeshPro">
<HintPath>lib/TextMeshPro-1.0.55.56.0b9.dll</HintPath> <HintPath>lib/TextMeshPro-1.0.55.56.0b9.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>