Skip to content

feat(tools): 成就图片生成器支持任意语言、自定义图标与字体 - #3654

Closed
meixuan1234 wants to merge 1 commit into
PCL-Community:devfrom
meixuan1234:feat/achievement-custom-i18n
Closed

meixuan1234 wants to merge 1 commit into
PCL-Community:devfrom
meixuan1234:feat/achievement-custom-i18n

Conversation

@meixuan1234

@meixuan1234 meixuan1234 commented Oct 5, 2026 •

Copy link
Copy Markdown

背景

「百宝箱 → 自定义成就图片生成器」原先调用第三方接口 minecraft-api.com 生成图片,
而该接口不支持非 ASCII 字符,输入中文会直接返回 404,因此界面只能标注「仅支持英文」。

本 PR 将其改为完全本地渲染,不再依赖任何图片生成服务。

主要改动

原实现 现在
生成方式 调用 minecraft-api.com WPF DrawingVisual 本地绘制
语言 仅 ASCII 任意语言
换行 依赖服务端 按像素宽度自动换行(含连续 ASCII 串)
卡片高度 固定 随内容自适应
字体 不可选 内置像素字体 + 可切换本机字体
图标 依赖服务端 实例资源 → 在线接口 → 屏障占位 → 内置图形
自定义图标 无 支持选择本地图片

其它体验改进:

  • 输入框下方字数提示(超 20 字蓝字、达 55 字红字并限制输入)
  • 各输入框补充悬浮说明
  • 「物品名(ID)」改为「物品 ID(自动匹配图标)」

⚠️ 需要维护者决策的两点

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 判断无效(其初始值为空字符串)

验证情况

  • Debug / Release 均编译通过(0 error)
  • 已在本机运行测试:中文渲染、长文本换行、字体切换、自定义图标、字数提示、
    图标多级兜底均正常
  • Release 单文件版已打包给朋友试用

Fixes #1566

Sourcery 摘要

将成就图片生成器改为支持多语言、自定义字体和图标的本地渲染方案,并修复相关工具页面的既有问题。

新功能:

  • 支持在本地生成可显示任意语言的成就图片,并根据内容自动换行和调整卡片高度。
  • 支持选择内置或系统字体,以及使用本地图标并自动匹配实例、在线或占位图标。
  • 新增成就图片预览、PNG 保存、输入长度提示和相关界面辅助说明。

错误修复:

  • 修复原成就图片生成对第三方服务和 ASCII 文本的限制。
  • 修复原版清理逻辑无法识别并删除 *-natives 目录的问题。
  • 修复调整头部尺寸时对空皮肤路径判断无效的问题。

改进:

  • 改进成就图片的视觉呈现,包括像素风格字体、阴影、边框和高分辨率渲染。
Original summary in English

Sourcery 摘要

将成就图片生成器改为支持多语言、自定义字体与图标的本地渲染方案,并修复相关工具页面的问题。

新功能:

  • 支持在本地生成可显示任意语言的成就图片,并根据内容自动换行和调整卡片高度。
  • 支持选择内置或系统字体,以及使用本地图标、实例资源和在线资源自动匹配成就图标。
  • 新增成就图片预览、PNG 保存、可选自定义图标和输入长度提示。

问题修复:

  • 移除对第三方图片生成服务的依赖,解决中文等非 ASCII 文本无法生成成就图片的问题。
  • 修复清理逻辑无法识别 *-natives 目录以及头部尺寸调整时空皮肤路径判断无效的问题。

改进:

  • 改进成就图片的视觉呈现,并为图标加载提供多级回退机制。
Original summary in English

Summary by Sourcery

将成就图片生成器改为支持多语言、自定义字体与图标的本地渲染方案,并修复相关工具页面的问题。

New Features:

  • 支持在本地生成可显示任意语言的成就图片,并根据内容自动换行和调整卡片高度。
  • 支持选择内置或系统字体,以及使用本地图标、实例资源和在线资源自动匹配成就图标。
  • 新增成就图片预览、PNG 保存、可选自定义图标和输入长度提示。

Bug Fixes:

  • 移除对第三方图片生成服务的依赖,解决中文等非 ASCII 文本无法生成成就图片的问题。
  • 修复清理逻辑无法识别 *-natives 目录以及头部尺寸调整时空皮肤路径判断无效的问题。

Enhancements:

  • 改进成就图片的视觉呈现,并为图标加载提供多级回退机制。

@pcl-ce-automation pcl-ce-automation Bot added 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 size: XXL PR 大小评估:巨型 labels Oct 5, 2026
@sourcery-ai

sourcery-ai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

评审者指南

本 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
Loading

自适应成就卡片渲染流程图

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"]
Loading

文件级变更

变更 详情 文件
将成就图片生成从第三方接口迁移为 WPF 本地渲染,并支持任意语言与自适应排版。
  • 使用 DrawingVisual、FormattedText 和高倍栅格化绘制卡片、边框、阴影及图标占位图。
  • 按字体实际像素宽度手动换行,支持连续 ASCII 串、手动换行和动态卡片高度。
  • 清理 Minecraft 格式代码并提供内置像素字体及本机字体切换。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
增加成就图标的本地、自定义与在线多级获取机制。
  • 支持选择本地图片作为优先图标。
  • 按实例资源、多个在线接口、内置或在线屏障图标依次回退,并缓存在线结果。
  • 实例资源读取同时覆盖 item 与 block 贴图,全部失败时绘制稳定配色的等轴立方体占位图。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
完善成就编辑界面交互、校验和保存流程。
  • 增加字体选择、自定义图标入口、输入框悬浮说明及本地化提示。
  • 增加 20/55 字长度提示、粘贴内容截断和预览/保存状态刷新。
  • 预览和保存共用异步图标加载与本地 PNG 编码流程,避免网络加载期间阻塞界面。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
修复两个既有的目录清理和皮肤尺寸切换缺陷。
  • 使用大小写不敏感的后缀判断正确识别 *-natives 目录。
  • 改为空字符串判断,避免无效的非空路径检查。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
引入成就渲染所需的内置字体与图标资源。
  • 新增 16MB 像素字体资源以覆盖中文等非 ASCII 字形。
  • 新增内置屏障图标资源,并由项目资源规则嵌入程序集。
Plain Craft Launcher 2/Resources/AchievementFont.ttf
Plain Craft Launcher 2/Resources/AchievementBarrier.png
Plain Craft Launcher 2/Plain Craft Launcher 2.csproj

与关联 Issue 的评估

Issue 目标 已解决 说明
#1566 使“百宝箱 → 自定义成就图片生成器”支持输入并生成包含中文等非 ASCII 语言的成就名称和描述。 ✅
#1566 确保成就图片生成不再因第三方接口不支持中文而失败,并提供可用的本地渲染与保存流程。 ✅

提示与命令

与 Sourcery 交互

  • 触发新的评审: 在 pull request 中评论 @sourcery-ai review。
  • 继续讨论: 直接回复 Sourcery 的评审评论。
  • 根据评审评论生成 GitHub Issue: 回复评审评论,请 Sourcery 根据该评论创建 Issue。也可以回复 @sourcery-ai issue,根据该评论创建 Issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写入 @sourcery-ai,即可随时生成标题。也可以在 pull request 中评论 @sourcery-ai title,随时重新生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中需要生成摘要的位置写入 @sourcery-ai summary,即可在指定位置生成 PR 摘要。也可以在 pull request 中评论 @sourcery-ai summary,随时重新生成摘要。
  • 生成评审者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时重新生成评审者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这会非常有用。
  • 忽略所有 Sourcery 评审: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 评审。如果你想从新的评审开始,这会特别有用——别忘了评论 @sourcery-ai review 以触发新的评审!

自定义使用体验

访问你的控制面板即可:

  • 启用或禁用评审功能,例如 Sourcery 生成的 pull request 摘要、评审者指南等。
  • 更改评审语言。
  • 添加、删除或编辑自定义评审说明。
  • 调整其他评审设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 移除成就图片对 minecraft-api.com 的依赖,改用 WPF 完全本地渲染,提供任意语言、自适应换行、字体切换、自定义图标及多级图标兜底,同时完善交互提示并修复两个既有缺陷;评审时还应重点确认新增字体的体积与授权、在线图标源的可用性,以及异步加载和资源缓存的线程安全性。

Sequence diagram for local achievement image generation

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
Loading

Flow diagram for adaptive achievement card rendering

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"]
Loading

File-Level Changes

Change Details Files
将成就图片生成从第三方接口迁移为 WPF 本地渲染,并支持任意语言与自适应排版。
  • 使用 DrawingVisual、FormattedText 和高倍栅格化绘制卡片、边框、阴影及图标占位图。
  • 按字体实际像素宽度手动换行,支持连续 ASCII 串、手动换行和动态卡片高度。
  • 清理 Minecraft 格式代码并提供内置像素字体及本机字体切换。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
增加成就图标的本地、自定义与在线多级获取机制。
  • 支持选择本地图片作为优先图标。
  • 按实例资源、多个在线接口、内置或在线屏障图标依次回退,并缓存在线结果。
  • 实例资源读取同时覆盖 item 与 block 贴图,全部失败时绘制稳定配色的等轴立方体占位图。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
完善成就编辑界面交互、校验和保存流程。
  • 增加字体选择、自定义图标入口、输入框悬浮说明及本地化提示。
  • 增加 20/55 字长度提示、粘贴内容截断和预览/保存状态刷新。
  • 预览和保存共用异步图标加载与本地 PNG 编码流程,避免网络加载期间阻塞界面。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
修复两个既有的目录清理和皮肤尺寸切换缺陷。
  • 使用大小写不敏感的后缀判断正确识别 *-natives 目录。
  • 改为空字符串判断,避免无效的非空路径检查。
Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
引入成就渲染所需的内置字体与图标资源。
  • 新增 16MB 像素字体资源以覆盖中文等非 ASCII 字形。
  • 新增内置屏障图标资源,并由项目资源规则嵌入程序集。
Plain Craft Launcher 2/Resources/AchievementFont.ttf
Plain Craft Launcher 2/Resources/AchievementBarrier.png
Plain Craft Launcher 2/Plain Craft Launcher 2.csproj

Assessment against linked issues

Issue Objective Addressed Explanation
#1566 使“百宝箱 → 自定义成就图片生成器”支持输入并生成包含中文等非 ASCII 语言的成就名称和描述。 ✅
#1566 确保成就图片生成不再因第三方接口不支持中文而失败,并提供可用的本地渲染与保存流程。 ✅

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嘿——我发现了 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>

Sourcery 对开源项目免费提供服务——如果您喜欢我们的审查结果,请考虑分享它们 ✨
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>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
Comment thread Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs Outdated
原先该功能依赖第三方接口 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 等),
  但图片内渲染的标题仍保持原样
@meixuan1234
meixuan1234 force-pushed the feat/achievement-custom-i18n branch from b704815 to 102b9ad Compare October 5, 2026 12:36
@meixuan1234

Copy link
Copy Markdown
Author

感谢评审!两个问题都属实,已修复并推送到同一分支(commit 102b9ad),无需新开 PR。

1. OnlineIconCache 并发风险

TryLoadOnlineIcon 是在 Task.Run 的线程池里执行的,而「预览」「保存」在生成期间并不禁用 —— 用户连续点击会让两个任务同时读写这个普通 Dictionary。并发写入会破坏其内部的桶数组结构,可能抛异常,甚至让后续查找陷入死循环。

修复:

  • 缓存类型改为 ConcurrentDictionary
  • 新增 _isRenderingAchievement 标志,生成期间禁用两个按钮
  • 两个事件入口再加一层 if (_isRenderingAchievement) return; 兜底
  • finally 中恢复标志并刷新按钮状态

2. 默认文件名含 Windows 非法字符

Windows 禁止文件名包含 < > : " / \ | ? * 与控制字符;且 CON、PRN、AUX、NUL、COM1… 这类设备名即使带扩展名也无法创建(CON.txt 同样失败)。

修复:新增 SanitizeFileName():

  • 非法字符与控制字符替换为下划线
  • 去掉结尾的空格与点
  • 识别保留设备名并加下划线前缀
  • 清理后为空时回退为 achievement

只清理保存对话框的默认文件名,图片内渲染的标题保持原样。

@LuLu-ling LuLu-ling left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

请严格遵守 技术规范 重新修整你的 PR:

  1. PR 中的所有 Commit 必须要附带有效的、已验证的签名。参考 提交信息规范-提交签名要求 章节与 GPG 签名配置指南。
  2. 如果使用了任意 AI 工具,应该在 PR 提交信息或者 Commit 信息内注明使用的模型、工具信息等。参考 AI 工具使用规范。

@meixuan1234

meixuan1234 commented Oct 5, 2026 via email

Copy link
Copy Markdown
Author

@MoYuan-CN MoYuan-CN left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

参见下方意见
此外,你提交了一个 15.4 MB 的字体资源文件是什么鬼啊……

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不应当在这里提交除了 en-US 和 zh-CN 以外的语言,撤销掉这个提交

@meixuan1234

meixuan1234 commented Oct 5, 2026 via email

Copy link
Copy Markdown
Author

@Chiloven945 Chiloven945 closed this Oct 5, 2026
@pcl-ce-automation pcl-ce-automation Bot removed 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 size: XXL PR 大小评估:巨型 labels Oct 5, 2026
@Big-Cake-jpg

Copy link
Copy Markdown
Member

根据 AI 工具使用规范,我们不接受任何未经审查、完全由 AI 生成的大型 PR。若后续继续出现类似行为,您可能会被剥夺向 PCL CE 作出贡献的权利。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

在百宝箱-自定义成就图片生成器中添加中文支持

5 participants