Skip to content

refactor(downloader): 重构下载器分片与系统资源分配逻辑 - #3506

Draft
Pigeon0v0 wants to merge 14 commits into
devfrom
refactor/downloader-range
Draft

refactor(downloader): 重构下载器分片与系统资源分配逻辑#3506
Pigeon0v0 wants to merge 14 commits into
devfrom
refactor/downloader-range

Conversation

@Pigeon0v0

@Pigeon0v0 Pigeon0v0 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

本 PR 尚未经过全面人工 review,因此暂时 Draft


本 PR 对下载器的分片策略与系统资源分配进行了重构。

修改内容:针对文件下载回退到 HTTP/1.1(至少在我这里高峰期 1.1 的速度显著快于 2.0),元数据与 API 请求仍然使用 HTTP/2.0;仅针对大于 4 MiB 的文件尝试分片;批量任务中未知大小的文件直接下载,不进行 Range 探测;大文件下载采用新的动态分片机制,分片大小更加灵活;内存缓存改为全局共享,并及时将内容写入硬盘,避免极端情况下内存过高占用。

测试时进行 Minecraft 26.2 清洁安装,下载高峰阶段相比 PCL 2.13.1.0 的相同阶段内存占用可减少约 2/3(稳定在 180 - 220 MB),同时保持下载速度基本持平甚至略微更快;与 PCL CE 2.15.0 相比内存占用差距不大(此 PR 版本占用略微减少),主要改进了部分情况下下载速度极其缓慢的问题。

同时,close #3356

本 PR 主要使用 AI 完成,因此需要较为细致的测试与检查。同时,回退到 HTTP/1.1 还是保留 HTTP/2.0 可能仍需要进一步调查与讨论。

Generated by GPT-5.6 Sol xHigh & GPT-5.6 Terra xHigh

Summary by Sourcery

重构下载器,使用新的自适应基于范围的分段机制并引入共享的全局资源管理,从而改进内存使用和大文件性能,同时重构配置和 UI,使其以“连接数”而非“线程数”的方式进行交互。

Enhancements:

  • 将每个文件基于多块的 DownloadService 使用方式替换为:内部顺序下载器以及仅在文件足够大时才启用的自适应基于范围的并行下载器。
  • 引入 DownloadResourceManager,在全局范围内协调所有下载的 HTTP 连接、共享缓冲区和带宽限速。
  • 将网络配置从基于线程的限制重构为基于连接的限制,包括每文件连接数限制和主机级约束,并为现有设置提供向后兼容的映射。
  • 调整加载器逻辑,以便在校验和验证通过后更好地重用已有文件,并避免对小文件或大小未知的文件进行不必要的范围探测。
  • 更新 UI、配置和监控界面(例如速度面板、设置滑块),使其显示连接数和新的每文件连接设置,而非线程数。
Original summary in English

Summary by Sourcery

Refactor the downloader to use a new adaptive range-based segmentation mechanism with shared global resource management, improving memory usage and large-file performance while reworking configuration and UI to talk in terms of connections rather than threads.

Enhancements:

  • Replace the per-file multi-chunk DownloadService usage with an internal sequential downloader and an adaptive range-based parallel downloader that only engages for sufficiently large files.
  • Introduce DownloadResourceManager to globally coordinate HTTP connections, shared buffers, and bandwidth throttling across all downloads.
  • Rework network configuration from thread-based limits to connection-based limits, including per-file connection limits and host-level constraints, with backward-compatible mapping for existing settings.
  • Adjust loader logic to better reuse existing files after checksum verification and to avoid unnecessary range probes for small or unknown-size files.
  • Update UI, config, and monitoring surfaces (e.g., speed panel, settings sliders) to reflect connection counts and new per-file connection settings instead of thread counts.

@pcl-ce-automation pcl-ce-automation Bot added 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中 size: XXL PR 大小评估:巨型 labels Aug 5, 2026
@sourcery-ai

sourcery-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

审阅者指南

重构下载器,使用自定义的自适应分段(range-based)多连接实现,并集中管理资源(连接、缓冲区、带宽);将原先基于“线程”的单文件限制改为基于“连接”的限制;更新 UI / 配置绑定;并对小文件与大文件 / 未知大小文件引入不同的处理方式,以改善内存占用和下载性能。

自适应下载流 vs 顺序下载流的时序图

sequenceDiagram
    actor User
    participant LoaderDownload as LoaderDownload
    participant FileDownloader as FileDownloader
    participant AdaptiveRangeDownloader as AdaptiveRangeDownloader
    participant DownloadResourceManager as DownloadResourceManager
    participant HttpClient as HttpClient

    User->>LoaderDownload: ProcessFileAsync(file)
    LoaderDownload->>FileDownloader: DownloadSingleAsync(url, localPath, enableParallelChunks)
    alt enableParallelChunks
        FileDownloader->>AdaptiveRangeDownloader: TryDownloadAsync(url, localPath, useBrowserUA, customUA, expectedSize)
        alt large_file_with_range
            AdaptiveRangeDownloader->>DownloadResourceManager: AcquireConnectionAsync(url)
            AdaptiveRangeDownloader->>HttpClient: SendAsync(range_request)
            HttpClient-->>AdaptiveRangeDownloader: PartialContent
            loop per_segment
                AdaptiveRangeDownloader->>DownloadResourceManager: ReserveBufferAsync(BufferSize)
                AdaptiveRangeDownloader->>DownloadResourceManager: ThrottleAsync(bytes)
                AdaptiveRangeDownloader->>DownloadResourceManager: RecordDownloadedBytes(bytes)
            end
            AdaptiveRangeDownloader-->>FileDownloader: true
            FileDownloader->>FileDownloader: PromoteTempFile(localPath)
            FileDownloader->>FileDownloader: MarkDownloadCompleted(trackedFile)
        else range_not_supported_or_small
            AdaptiveRangeDownloader-->>FileDownloader: false
            FileDownloader->>FileDownloader: DownloadSequentiallyAsync(...)
        end
    else !enableParallelChunks
        FileDownloader->>FileDownloader: DownloadSequentiallyAsync(...)
    end

    FileDownloader->>DownloadResourceManager: AcquireConnectionAsync(url)
    FileDownloader->>HttpClient: SendAsync(request)
    HttpClient-->>FileDownloader: Response
    loop read_stream
        FileDownloader->>DownloadResourceManager: ReserveBufferAsync(bufferSize)
        FileDownloader->>DownloadResourceManager: ThrottleAsync(bytes)
        FileDownloader->>DownloadResourceManager: RecordDownloadedBytes(bytes)
    end
    FileDownloader->>FileDownloader: PromoteTempFile(localPath)
    FileDownloader->>FileDownloader: MarkDownloadCompleted(trackedFile)
Loading

文件级变更

变更 详情 文件
将第三方基于 DownloadService 的单文件下载替换为自定义的顺序下载和自适应 Range(多连接)实现,包括临时文件提升及进度跟踪辅助方法。
  • 引入基于 HttpClient、共享缓冲池以及 DownloadResourceManager(用于限速和连接租赁)的 DownloadSequentiallyAsync。
  • 当启用并行分块时,将下载路由到 AdaptiveRangeDownloader.TryDownloadAsync,如果 Range 不合适或不被支持,则回退到顺序下载。
  • 新增帮助方法用于创建带签名的 HttpRequestMessage 实例、提升临时文件以及标记被跟踪的 DownloadFile 已完成。
  • 基于 Stopwatch 实现顺序下载进度计算,以保持 DownloadFile 上的速度和状态统计的准确性。
Plain Craft Launcher 2/Modules/Network/Downloader/FileDownloader.cs
引入 AdaptiveRangeDownloader,用于动态的基于 HTTP Range 的分段下载,支持慢连接检测、按段重试/拆分以及共享资源协调。
  • 探测服务器对精确 Range 响应的支持情况,对小文件或不支持的情况跳过 Range 模式。
  • 将大文件划分为多个分段,运行受每文件连接限制约束的多个 worker,并通过 RandomAccess.WriteAsync 直接将数据流写入预分配大小的临时文件。
  • 通过正在进行/已完成分段的吞吐量中位数来检测慢分段,当显著偏慢时重启或拆分分段,并对重试次数和分段扩张进行上限控制。
  • 与 DownloadResourceManager 集成,用于连接租赁、缓冲配额、限速以及统一的 DownloadFile 进度 / 速度上报。
Plain Craft Launcher 2/Modules/Network/Downloader/AdaptiveRangeDownloader.cs
新增 DownloadResourceManager 及相关配额 / 租约类型,用于在全局范围统一管理所有下载的 HTTP 连接、缓冲预算和下载带宽。
  • 使用基于 Stopwatch 的快照与原子计数器,跟踪活动连接数和聚合下载速度。
  • 通过 AsyncQuota 和 DownloadConnectionLease 强制执行全局及按主机的连接限制,并与 ModNet 的连接设置打通。
  • 实现用于池化缓冲区的缓冲预算预留,以及类似令牌桶的限速机制,遵守 NetTaskSpeedLimitHigh。
  • 提供可复用的配额原语(AsyncQuota、DownloadQuotaLease),以协同不同下载器之间的资源共享。
Plain Craft Launcher 2/Modules/Network/Downloader/DownloadResourceManager.cs
从基于线程的下载限制迁移为基于连接的限制,包括新的每文件连接上限、缓冲预算以及更新后的指标术语(threads → connections)。
  • 用 NetTaskConnectionLimit、NetTaskSingleFileConnectionLimit、最大常量以及缓冲预算替换 ModNet.NetTaskThreadLimit,同时保留 NetTaskThreadLimit 作为废弃别名。
  • 更新 LoaderDownload 的最大并行计算逻辑,改为使用 NetTaskConnectionLimit,并根据预期文件大小和批量大小调整是否启用并行分块。
  • 修改 NetManager,通过 DownloadResourceManager 计算 Speed 和 ConnectionCount,并提供废弃的 ThreadCount 兼容层。
  • 更新 PageSpeedLeft 和 ModSkin / Requester 相关路径,使用新的 NetDownloadEnd、连接计数以及调整后的 DownloadService 配置(更小的内存缓冲和固定块大小)。
Plain Craft Launcher 2/Modules/Network/Facade/ModNet.cs
Plain Craft Launcher 2/Modules/Network/Management/NetManager.cs
Plain Craft Launcher 2/Modules/Network/Loaders/LoaderDownload.cs
Plain Craft Launcher 2/Modules/Network/Http/Requester.cs
Plain Craft Launcher 2/Modules/Minecraft/ModSkin.cs
Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.cs
将新的连接限制设置和 UI 控件接入配置及初始化流程,包括每文件连接滑块及其持久化。
  • 新增 Config.Download.FileConnectionLimit,带向后兼容的键名和默认值,并在 ModSetup.ApplyAll 中完成绑定。
  • 引入 ToolDownloadFileConnection,将滑块数值映射到 NetTaskSingleFileConnectionLimit(带边界约束),同时更新 ToolDownloadThread 实现。
  • 扩展 PageSetupGameManage 的滑块,加入 SliderDownloadFileConnection,并调整总下载连接数的警告阈值。
  • 更新本地化 XAML 以及设置页 XAML,在 UI 中展示新的每文件连接设置(标签、描述、绑定)。
Plain Craft Launcher 2/Modules/Base/ModSetup.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml.cs
PCL.Core/App/Config.cs
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml
优化已下载文件以及小型 / 特殊下载的处理,以避免不必要的 Range 探测,并确保正确使用临时文件后缀。
  • 修改 LoaderDownload.ProcessFileAsync,在标记为复制并完成前,使用 FileChecker 重新检查已有文件(当有哈希时可选择异步卸载)。
  • 确保批量下载中未知大小的文件跳过 Range 探测:当 expectedSize < SmallFileThreshold 时禁用并行分块。
  • 为 Minecraft 索引下载设置 actualSize,避免对已知大小的元数据进行双重请求(探测 + 顺序下载)。
  • 统一所有调用点的 ModNet.NetDownloadEnd 使用方式,并修复大小写不一致问题(NetDownloadEnd vs netDownloadEnd)。
Plain Craft Launcher 2/Modules/Network/Loaders/LoaderDownload.cs
Plain Craft Launcher 2/Modules/Minecraft/ModDownload.cs
Plain Craft Launcher 2/Modules/Minecraft/ModSkin.cs
Plain Craft Launcher 2/Modules/Network/Facade/ModNet.cs

与关联 Issue 的对照评估

Issue 目标 是否解决 说明
#3356 修复 Minecraft 版本 11w49a 至 13w12~(例如 11w47a/11w49a)在处理 JSON / 索引下载时出错导致下载失败的 bug。

可能关联的 Issue


提示与命令

与 Sourcery 交互

  • 触发新的审阅: 在 Pull Request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论即可继续对话。
  • 从审阅评论生成 GitHub Issue: 在某条审阅评论下回复,请求 Sourcery 用该评论创建一个 Issue。你也可以直接回复 @sourcery-ai issue 来从该评论生成 Issue。
  • 生成 Pull Request 标题: 在 Pull Request 标题中任意位置写上 @sourcery-ai 即可随时生成标题。你也可以在 PR 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 Pull Request 摘要: 在 Pull Request 描述正文中任意位置写上 @sourcery-ai summary,即可在指定位置生成 PR 摘要。你也可以在 PR 中评论 @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

Refactors the downloader to use a custom adaptive range-based multi-connection implementation with centralized resource management (connections, buffers, bandwidth), replaces thread-based per-file limits with connection-based limits, updates UI/config bindings, and introduces different handling for small vs large/unknown-size files to improve memory usage and download performance.

Sequence diagram for adaptive vs sequential download flow

sequenceDiagram
    actor User
    participant LoaderDownload as LoaderDownload
    participant FileDownloader as FileDownloader
    participant AdaptiveRangeDownloader as AdaptiveRangeDownloader
    participant DownloadResourceManager as DownloadResourceManager
    participant HttpClient as HttpClient

    User->>LoaderDownload: ProcessFileAsync(file)
    LoaderDownload->>FileDownloader: DownloadSingleAsync(url, localPath, enableParallelChunks)
    alt enableParallelChunks
        FileDownloader->>AdaptiveRangeDownloader: TryDownloadAsync(url, localPath, useBrowserUA, customUA, expectedSize)
        alt large_file_with_range
            AdaptiveRangeDownloader->>DownloadResourceManager: AcquireConnectionAsync(url)
            AdaptiveRangeDownloader->>HttpClient: SendAsync(range_request)
            HttpClient-->>AdaptiveRangeDownloader: PartialContent
            loop per_segment
                AdaptiveRangeDownloader->>DownloadResourceManager: ReserveBufferAsync(BufferSize)
                AdaptiveRangeDownloader->>DownloadResourceManager: ThrottleAsync(bytes)
                AdaptiveRangeDownloader->>DownloadResourceManager: RecordDownloadedBytes(bytes)
            end
            AdaptiveRangeDownloader-->>FileDownloader: true
            FileDownloader->>FileDownloader: PromoteTempFile(localPath)
            FileDownloader->>FileDownloader: MarkDownloadCompleted(trackedFile)
        else range_not_supported_or_small
            AdaptiveRangeDownloader-->>FileDownloader: false
            FileDownloader->>FileDownloader: DownloadSequentiallyAsync(...)
        end
    else !enableParallelChunks
        FileDownloader->>FileDownloader: DownloadSequentiallyAsync(...)
    end

    FileDownloader->>DownloadResourceManager: AcquireConnectionAsync(url)
    FileDownloader->>HttpClient: SendAsync(request)
    HttpClient-->>FileDownloader: Response
    loop read_stream
        FileDownloader->>DownloadResourceManager: ReserveBufferAsync(bufferSize)
        FileDownloader->>DownloadResourceManager: ThrottleAsync(bytes)
        FileDownloader->>DownloadResourceManager: RecordDownloadedBytes(bytes)
    end
    FileDownloader->>FileDownloader: PromoteTempFile(localPath)
    FileDownloader->>FileDownloader: MarkDownloadCompleted(trackedFile)
Loading

File-Level Changes

Change Details Files
Replace third‑party DownloadService-based single-file download with custom sequential and adaptive range (multi-connection) implementations, including temp file promotion and progress tracking helpers.
  • Introduce DownloadSequentiallyAsync using HttpClient, shared buffer pool, and DownloadResourceManager for throttling and connection leasing.
  • Route downloads through AdaptiveRangeDownloader.TryDownloadAsync when parallel chunks are enabled, falling back to sequential download if range is unsuitable or unsupported.
  • Add helper methods for creating signed HttpRequestMessage instances, promoting temp files, and marking tracked DownloadFile completion.
  • Implement sequential download progress calculation based on Stopwatch to maintain accurate speed and state on DownloadFile.
Plain Craft Launcher 2/Modules/Network/Downloader/FileDownloader.cs
Introduce AdaptiveRangeDownloader for dynamic HTTP range-based segmented downloads with slow-connection detection, per-segment retry/splitting, and shared resource coordination.
  • Probe server support for precise Range responses, skipping range mode for small or unsupported files.
  • Partition large files into segments, run multiple workers bounded by per-file connection limits, and stream data directly into a pre-sized temp file via RandomAccess.WriteAsync.
  • Detect slow segments via median throughput of active/completed segments, restart or split segments when significantly slower, and cap retries and segment expansion.
  • Integrate with DownloadResourceManager for connection leasing, buffer quota, throttling, and unified DownloadFile progress/speed reporting.
Plain Craft Launcher 2/Modules/Network/Downloader/AdaptiveRangeDownloader.cs
Add DownloadResourceManager and supporting quota/lease types to globally manage HTTP connections, buffer budgets, and download bandwidth across all downloads.
  • Track active connection count and aggregate download speed using Stopwatch-based snapshots and atomic counters.
  • Enforce global and per-host connection limits using AsyncQuota and DownloadConnectionLease, wired to ModNet connection settings.
  • Implement buffer budget reservation for pooled buffers and a token-bucket-like throttling mechanism respecting NetTaskSpeedLimitHigh.
  • Provide reusable quota primitives (AsyncQuota, DownloadQuotaLease) to coordinate resource sharing between downloaders.
Plain Craft Launcher 2/Modules/Network/Downloader/DownloadResourceManager.cs
Shift from thread-based to connection-based download limits, including new per-file connection limits, buffer budget, and updated metrics terminology (threads → connections).
  • Replace ModNet.NetTaskThreadLimit with NetTaskConnectionLimit, NetTaskSingleFileConnectionLimit, max constants, and buffer budget, while keeping NetTaskThreadLimit as an obsolete alias.
  • Update LoaderDownload max-parallel calculation to use NetTaskConnectionLimit and adjust parallel-chunk enabling based on expected file size and batch size.
  • Change NetManager to compute Speed and ConnectionCount via DownloadResourceManager and provide an obsolete ThreadCount shim.
  • Update PageSpeedLeft and ModSkin / Requester code paths to use new NetDownloadEnd, connection counts, and adjusted DownloadService configuration (smaller memory buffer and fixed block size).
Plain Craft Launcher 2/Modules/Network/Facade/ModNet.cs
Plain Craft Launcher 2/Modules/Network/Management/NetManager.cs
Plain Craft Launcher 2/Modules/Network/Loaders/LoaderDownload.cs
Plain Craft Launcher 2/Modules/Network/Http/Requester.cs
Plain Craft Launcher 2/Modules/Minecraft/ModSkin.cs
Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.cs
Wire new connection-limit settings and UI controls into configuration and setup flow, including per-file connection slider and persistence.
  • Add Config.Download.FileConnectionLimit with backward-compatible key naming and default, and bind it in ModSetup.ApplyAll.
  • Introduce ToolDownloadFileConnection to map slider values to NetTaskSingleFileConnectionLimit with clamping, alongside updated ToolDownloadThread implementation.
  • Extend PageSetupGameManage sliders with SliderDownloadFileConnection and adjust warning threshold for total download connections.
  • Update localization XAMLs and settings page XAML to surface the new per-file connection setting in the UI (labels, descriptions, bindings).
Plain Craft Launcher 2/Modules/Base/ModSetup.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml.cs
PCL.Core/App/Config.cs
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/zh-CN.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml
Refine handling of already-downloaded files and small/special downloads to avoid unnecessary range probes and ensure correct temp suffix usage.
  • Change LoaderDownload.ProcessFileAsync to re-check existing files using FileChecker (optionally offloaded when hash is present) before marking as copy and finished.
  • Ensure unknown-size files in batch downloads skip range probing by disabling parallel chunks unless expectedSize ≥ SmallFileThreshold.
  • Set actualSize on Minecraft index downloads to prevent double requests (probe + sequential) for known-size metadata.
  • Normalize ModNet.NetDownloadEnd usage across all call sites and fix casing discrepancies (NetDownloadEnd vs netDownloadEnd).
Plain Craft Launcher 2/Modules/Network/Loaders/LoaderDownload.cs
Plain Craft Launcher 2/Modules/Minecraft/ModDownload.cs
Plain Craft Launcher 2/Modules/Minecraft/ModSkin.cs
Plain Craft Launcher 2/Modules/Network/Facade/ModNet.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#3356 Fix the bug where Minecraft versions 11w49a to 13w12~ (e.g., 11w47a/11w49a) fail to download due to issues handling their JSON/index downloads.

Possibly linked issues


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

# Conflicts:
#	PCL.Core/App/Localization/Languages/zh-CN.xaml
#	Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XXL PR 大小评估:巨型 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[正在调查]下载器在下载任务的末期可能出现速度异常 [C#]: 11w49a至13w12~的版本无法正常下载

1 participant