Repository navigation
feat(tools): 成就图片生成器支持任意语言、自定义图标与字体 - #3654
meixuan1234 wants to merge 1 commit into
Conversation
评审者指南本 PR 移除成就图片对 minecraft-api.com 的依赖,改用 WPF 完全本地渲染,提供任意语言、自适应换行、字体切换、自定义图标及多级图标兜底,同时完善交互提示并修复两个既有缺陷;评审时还应重点确认新增字体的体积与授权、在线图标源的可用性,以及异步加载和资源缓存的线程安全性。 本地成就图片生成时序图sequenceDiagram
actor User
participant PageToolsTest
participant IconLoader
participant Renderer
participant FileSystem
participant OnlineSources
User->>PageToolsTest: BtnAchievementPreview_Click()
PageToolsTest->>IconLoader: LoadAchievementIconAsync(itemId)
IconLoader->>FileSystem: TryLoadCustomIcon()
alt custom icon unavailable
IconLoader->>FileSystem: TryLoadVanillaIcon(itemId)
alt instance icon unavailable
IconLoader->>OnlineSources: TryLoadOnlineIcon(itemId)
alt online sources unavailable
IconLoader->>FileSystem: TryLoadBuiltInBarrier()
alt built-in barrier unavailable
IconLoader->>OnlineSources: LoadOnlineBarrier()
end
end
end
end
IconLoader-->>PageToolsTest: icon and notFound
PageToolsTest->>Renderer: RenderAchievementImage(icon)
Renderer-->>PageToolsTest: BitmapSource
PageToolsTest-->>User: Show local preview
自适应成就卡片渲染流程图flowchart LR
A["Achievement text and item ID"] --> B["StripMinecraftCodes"]
B --> C["ResolveAchievementFont"]
C --> D["WrapTextByWidth"]
D --> E["MeasureTextWidth"]
E --> F["Calculate adaptive card height"]
F --> G["RenderAchievementImage"]
G --> H["DrawingVisual and RenderTargetBitmap"]
H --> I["Preview or save PNG"]
文件级变更
与关联 Issue 的评估
提示与命令与 Sourcery 交互
自定义使用体验访问你的控制面板即可:
获取帮助Original review guide in EnglishReviewer's Guide本 PR 移除成就图片对 minecraft-api.com 的依赖,改用 WPF 完全本地渲染,提供任意语言、自适应换行、字体切换、自定义图标及多级图标兜底,同时完善交互提示并修复两个既有缺陷;评审时还应重点确认新增字体的体积与授权、在线图标源的可用性,以及异步加载和资源缓存的线程安全性。 Sequence diagram for local achievement image generationsequenceDiagram
actor User
participant PageToolsTest
participant IconLoader
participant Renderer
participant FileSystem
participant OnlineSources
User->>PageToolsTest: BtnAchievementPreview_Click()
PageToolsTest->>IconLoader: LoadAchievementIconAsync(itemId)
IconLoader->>FileSystem: TryLoadCustomIcon()
alt custom icon unavailable
IconLoader->>FileSystem: TryLoadVanillaIcon(itemId)
alt instance icon unavailable
IconLoader->>OnlineSources: TryLoadOnlineIcon(itemId)
alt online sources unavailable
IconLoader->>FileSystem: TryLoadBuiltInBarrier()
alt built-in barrier unavailable
IconLoader->>OnlineSources: LoadOnlineBarrier()
end
end
end
end
IconLoader-->>PageToolsTest: icon and notFound
PageToolsTest->>Renderer: RenderAchievementImage(icon)
Renderer-->>PageToolsTest: BitmapSource
PageToolsTest-->>User: Show local preview
Flow diagram for adaptive achievement card renderingflowchart LR
A["Achievement text and item ID"] --> B["StripMinecraftCodes"]
B --> C["ResolveAchievementFont"]
C --> D["WrapTextByWidth"]
D --> E["MeasureTextWidth"]
E --> F["Calculate adaptive card height"]
F --> G["RenderAchievementImage"]
G --> H["DrawingVisual and RenderTargetBitmap"]
H --> I["Preview or save PNG"]
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
嘿——我发现了 2 个问题
面向 AI Agent 的提示
请处理本次代码审查中的评论:
## 单独的评论
### 评论 1
<location path="Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs" line_range="1285-1308" />
<code_context>
+ if (OnlineIconCache.TryGetValue(itemId, out var cached)) return cached;
</code_context>
<issue_to_address>
**issue (bug_risk):** 当 `LoadAchievementIconAsync` 处于等待状态时,预览和保存按钮仍保持启用,因此连续两次点击可能会并发执行 `TryLoadOnlineIcon`。非线程安全的 `Dictionary` 会被不同的线程池操作同时读取和写入,当请求并发完成时,可能抛出异常或导致缓存损坏。
**触发条件:** 用户在第一个图标请求完成前点击“预览”和“保存”,或反复点击任一操作。
**建议修复:** 使用锁或并发字典保护 `OnlineIconCache`,并在当前渲染完成前禁用成就相关操作。
</issue_to_address>
### 评论 2
<location path="Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs" line_range="818-819" />
<code_context>
+ encoder.Save(buffer);
+ buffer.Position = 0;
+
+ var path = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Achievement.Save"),
+ AchievementTitleTextBox.Text + ".png", Lang.Text("Tools.Test.Achievement.FileFilter"));
+ if (string.IsNullOrEmpty(path))
+ {
+ ModBase.Log("用户取消了保存操作");
</code_context>
<issue_to_address>
**issue (bug_risk):** 默认保存文件名直接由用户输入的成就标题构成。文本框允许输入包含 Windows 无效文件名字符(例如 `\`、`/`、`:`、`*`、`?`、`"`、`<`、`>` 或 `|`)的标题,这会导致保存对话框初始化或保存操作失败,而不是让用户保存生成的图像。
**触发条件:** 成就标题包含 Windows 无效文件名字符时。
**建议修复:** 在将标题作为默认文件名传递之前对其进行清理,同时保留渲染图像中的完整标题。
```suggestion
var safeTitle = AchievementTitleTextBox.Text;
foreach (var invalidChar in Path.GetInvalidFileNameChars())
safeTitle = safeTitle.Replace(invalidChar, '_');
var path = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Achievement.Save"),
safeTitle + ".png", Lang.Text("Tools.Test.Achievement.FileFilter"));
```
</issue_to_address>Original comment in English
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs" line_range="1285-1308" />
<code_context>
+ if (OnlineIconCache.TryGetValue(itemId, out var cached)) return cached;
</code_context>
<issue_to_address>
**issue (bug_risk):** The preview and save buttons remain enabled while `LoadAchievementIconAsync` is awaiting, so two clicks can execute `TryLoadOnlineIcon` concurrently. The non-thread-safe `Dictionary` is read and written from separate thread-pool operations, which can throw or corrupt the cache when requests complete concurrently.
**Triggers:** When the user clicks Preview and Save, or clicks either action repeatedly, before the first icon request completes.
**Suggested fix:** Protect `OnlineIconCache` with a lock/concurrent dictionary, and disable the achievement actions until the current render completes.
</issue_to_address>
### Comment 2
<location path="Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs" line_range="818-819" />
<code_context>
+ encoder.Save(buffer);
+ buffer.Position = 0;
+
+ var path = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Achievement.Save"),
+ AchievementTitleTextBox.Text + ".png", Lang.Text("Tools.Test.Achievement.FileFilter"));
+ if (string.IsNullOrEmpty(path))
+ {
+ ModBase.Log("用户取消了保存操作");
</code_context>
<issue_to_address>
**issue (bug_risk):** The default save filename is built directly from the user-entered achievement title. Titles containing Windows-invalid filename characters such as `\`, `/`, `:`, `*`, `?`, `"`, `<`, `>`, or `|` are accepted by the text box, causing the save dialog initialization or save operation to fail instead of allowing the user to save the generated image.
**Triggers:** When the achievement title contains a Windows-invalid filename character.
**Suggested fix:** Sanitize the title before passing it as the default filename, while preserving the full title inside the rendered image.
```suggestion
var safeTitle = AchievementTitleTextBox.Text;
foreach (var invalidChar in Path.GetInvalidFileNameChars())
safeTitle = safeTitle.Replace(invalidChar, '_');
var path = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Achievement.Save"),
safeTitle + ".png", Lang.Text("Tools.Test.Achievement.FileFilter"));
```
</issue_to_address>原先该功能依赖第三方接口 minecraft-api.com 生成图片,而该接口不支持非 ASCII 字符,输入中文会直接返回 404,因此界面只得标注「仅支持英文」。本次改为完全本地 渲染,彻底摆脱该限制。 主要改动 - 用 WPF 的 DrawingVisual 本地绘制成就卡片,不再调用任何图片生成接口 - 字体默认使用内置像素字体,也可在下拉框中改用本机已安装的任意字体 - 描述文字按像素宽度自动换行(含连续 ASCII 串),卡片高度随内容自适应 - 物品图标改为多级兜底:实例资源 -> 在线接口 -> 屏障占位图 -> 内置图形 - 支持通过「浏览」指定本地图片作为图标 - 输入框下方给出字数提示:超过 20 字为蓝字,达到 55 字为红字并限制继续输入 - 为各输入框补充悬浮说明;「物品名(ID)」改为「物品 ID(自动匹配图标)」 顺带修复 - RubbishClear 中 natives 目录的判断条件恒为 false,导致该清理分支从未生效 - CmbHeadSize_SelectionChanged 中 skinPath 的判空无效(它的初始值是空字符串) BREAKING CHANGE: 移除对 minecraft-api.com 的依赖,成就图片改为本地生成 同时修复评审中指出的两个并发/健壮性问题 - OnlineIconCache 改为 ConcurrentDictionary,并在生成期间禁用「预览」「保存」, 避免用户连续点击导致多个任务并发读写普通 Dictionary 而破坏其内部结构 - 保存时清理默认文件名中的 Windows 非法字符与保留设备名(CON、PRN 等), 但图片内渲染的标题仍保持原样
b704815 to
102b9ad
Compare
|
感谢评审!两个问题都属实,已修复并推送到同一分支(commit 1.
|
There was a problem hiding this comment.
请严格遵守 技术规范 重新修整你的 PR:
- PR 中的所有 Commit 必须要附带有效的、已验证的签名。参考 提交信息规范-提交签名要求 章节与 GPG 签名配置指南。
- 如果使用了任意 AI 工具,应该在 PR 提交信息或者 Commit 信息内注明使用的模型、工具信息等。参考 AI 工具使用规范。
|
收到,立马整改
…________________________________
发件人: 庐庐绫 ***@***.***>
发送时间: 2026年10月5日 20:38
收件人: PCL-Community/PCL-CE ***@***.***>
抄送: 霉轩 ***@***.***>; Author ***@***.***>
主题: Re: [PCL-Community/PCL-CE] feat(tools): 成就图片生成器支持任意语言、自定义图标与字体 (PR #3654)
@LuLu-ling requested changes on this pull request.
请严格遵守 技术规范<https://docs.pclc.cc/ce/developers/guidelines> 重新修整你的 PR:
1. PR 中的所有 Commit 必须要附带有效的、已验证的签名。参考 提交信息规范-提交签名要求 章节与 GPG 签名配置指南<https://docs.pclc.cc/ce/developers/gpg-signing>。
2. 如果使用了任意 AI 工具,应该在 PR 提交信息或者 Commit 信息内注明使用的模型、工具信息等。参考 AI 工具使用规范<https://docs.pclc.cc/ce/developers/guidelines#ai-%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E8%A7%84%E8%8C%83>。
―
Reply to this email directly, view it on GitHub<#3654?email_source=notifications&email_token=BQUVTN6FBUDSOWTAMNG3YCD5SOI5BA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGQ2TQNJXGYYKM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#pullrequestreview-5414585760>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BQUVTN2EI5UVOCQG7Z6BGYT5SOI5BAVCNFSNUABFKJSXA33TNF2G64TZHM3TQNRTGUYDCOBQHNEXG43VMU5TKNZRGE4TINZYGU3KC5QC>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/BQUVTN4RAXCPG37FCXBSYSL5SOI5BA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGQ2TQNJXGYYKM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG> and Android<https://github.com/notifications/mobile/android/BQUVTN3RIYP3XLY72EO2LTT5SOI5BA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGQ2TQNJXGYYKM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA>. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
MoYuan-CN
left a comment
There was a problem hiding this comment.
参见下方意见
此外,你提交了一个 15.4 MB 的字体资源文件是什么鬼啊……
There was a problem hiding this comment.
不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交
There was a problem hiding this comment.
不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交
|
呃,那是MC成就字体
…________________________________
发件人: 墨渊 ***@***.***>
发送时间: 2026年10月5日 21:29
收件人: PCL-Community/PCL-CE ***@***.***>
抄送: 霉轩 ***@***.***>; Author ***@***.***>
主题: Re: [PCL-Community/PCL-CE] feat(tools): 成就图片生成器支持任意语言、自定义图标与字体 (PR #3654)
@MoYuan-CN requested changes on this pull request.
参见下方意见
此外,你提交了一个 15.4 MB 的字体资源文件是什么鬼啊……
________________________________
On PCL.Core/App/Localization/Languages/en-GB.xaml<#3654 (comment)>:
不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交
________________________________
On PCL.Core/App/Localization/Languages/zh-TW.xaml<#3654 (comment)>:
不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交
―
Reply to this email directly, view it on GitHub<#3654?email_source=notifications&email_token=BQUVTN7TL22Z3UM3ISEJEAD5SOO4DA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGUYTSMZWGY22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#pullrequestreview-5415193665>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BQUVTN3R5S2SPWCBIHUS3PT5SOO4DAVCNFSNUABFKJSXA33TNF2G64TZHM3TQNRTGUYDCOBQHNEXG43VMU5TKNZRGE4TINZYGU3KC5QC>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/BQUVTN2N6FFPRFWEPN7TUPL5SOO4DA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGUYTSMZWGY22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG> and Android<https://github.com/notifications/mobile/android/BQUVTN34AYGV3QWXWY37XPL5SOO4DA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNBRGUYTSMZWGY22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA>. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
|
根据 AI 工具使用规范,我们不接受任何未经审查、完全由 AI 生成的大型 PR。若后续继续出现类似行为,您可能会被剥夺向 PCL CE 作出贡献的权利。 |
背景
「百宝箱 → 自定义成就图片生成器」原先调用第三方接口
minecraft-api.com生成图片,而该接口不支持非 ASCII 字符,输入中文会直接返回 404,因此界面只能标注「仅支持英文」。
本 PR 将其改为完全本地渲染,不再依赖任何图片生成服务。
主要改动
DrawingVisual本地绘制其它体验改进:
1. 内置字体体积
为支持像素风格的中文,内置了
Resources/AchievementFont.ttf(16MB),主程序集会从约 5MB 增加到约 21MB。
该字体取自 MIT 许可的第三方项目
timetetng/minecraft_achievement_enerator。如果体积不可接受,我可以改为子集化(仅保留常用汉字,预计可压到 1~2MB),
或者干脆不内置、改用系统字体 + 用户自行指定字体文件。请指示倾向。
2. 字体授权
该字体随上述 MIT 项目分发,但其原始作者与授权范围未能确认。
若不便使用,我可以替换为授权明确的字体(如 Zpix 最像素)。
顺带修复的两个既有缺陷
RubbishClear:dirInfo2.Name == dirInfo2.Name + "-natives"恒为 false,导致
*-natives目录的清理分支从未生效CmbHeadSize_SelectionChanged:skinPath is not null判断无效(其初始值为空字符串)验证情况
图标多级兜底均正常
Fixes #1566
Sourcery 摘要
将成就图片生成器改为支持多语言、自定义字体和图标的本地渲染方案,并修复相关工具页面的既有问题。
新功能:
错误修复:
改进:
Original summary in English
Sourcery 摘要
将成就图片生成器改为支持多语言、自定义字体与图标的本地渲染方案,并修复相关工具页面的问题。
新功能:
问题修复:
改进:
Original summary in English
Summary by Sourcery
将成就图片生成器改为支持多语言、自定义字体与图标的本地渲染方案,并修复相关工具页面的问题。
New Features:
Bug Fixes:
Enhancements: