Kotlin/Gradle 独立工程,提供 Minecraft Java 世界优化功能:扫描各维度的 region/entities/poi MCA 文件,根据 InhabitedTime 阈值与强制加载列表(chunks.dat)保留区块并重写输出,同时支持进度与可选压缩输出。
- 构建可执行 JAR:
./gradlew :app:shadowJar --no-daemon- 产物位置:app/build/libs/backup-.jar(版本由根项目统一注入)
- 运行示例:
# 指定输入与输出目录
java -jar app/build/libs/backup-0.1.0.jar /path/to/world /path/to/out -t 600 --zip-output
# 原地处理(覆盖输入目录)
java -jar app/build/libs/backup-0.1.0.jar /path/to/world --in-place --progress-mode global
# 写入报告文件(JSON 或 CSV)
java -jar app/build/libs/backup-0.1.0.jar /path/to/world /path/to/out -t 0 --report-file /tmp/report.json --report-format json- WORLD_DIR:世界根目录
- OUTPUT_DIR:输出目录(可选;非原地模式时必须为空,除非使用 --force 清空覆盖)
- -t, --inhabited-time-seconds:InhabitedTime 阈值(秒,1 秒=20 tick,默认 300)
- --remove-unknown:将未知/外部压缩的区块视为可删除
- --progress-mode:Off | Global | Region(默认 Region)
- --in-place:原地处理,忽略输出目录并替换输入目录
- --zip-output:将输出目录打包为时间戳 zip 并删除目录
- -f, --force:覆盖已存在且非空的输出目录(无交互)
- --strict:严格模式,遇到损坏的 MCA 或解析失败时返回非零退出码
- --report:在标准输出打印处理统计与错误列表
- --report-file:将报告写入文件(支持 JSON/CSV)
- --report-format:json | csv(默认 json)
- --progress-interval:进度回调的区块粒度(默认 1000)
- --progress-interval-ms:进度回调的时间粒度,>0 时优先使用(默认 0)
- --parallelism:并行处理维度的线程数(默认 1)
- --copy-misc:非原地模式下,将每个维度目录中除 region/entities/poi 以外的文件与文件夹复制到输出对应维度目录(默认 true;支持否定形式:--copy-misc=false 或 --no-copy-misc)
- 公共Maven仓库发布地址
- 发布到本地 Maven 仓库:
./gradlew :core:publishToMavenLocal --no-daemon
- 依赖声明:
dependencies { implementation("io.github.wangzhizhou:backup-core:<version>") }
最小化示例(默认值):
import com.jokerhub.orzmc.world.*
import java.nio.file.Paths
fun minimal() {
val report = Optimizer.run(Paths.get("/path/to/world"), Paths.get("/path/to/out"))
println(ReportIO.toJson(report))
}进阶示例(更短 DSL + 自动补全扩展名):
import com.jokerhub.orzmc.world.*
import java.nio.file.Paths
fun advanced() {
val report = Optimizer.run(Paths.get("/path/to/world"), Paths.get("/path/to/out")) {
inhabitedThresholdSeconds = 0
strict = true
inPlace = false
zipOutput = true
progressSink = { e -> println(e) }
reportFormat = "csv"
reportSink = "/path/to/report"
}
println(ReportIO.toJson(report))
}import com.jokerhub.orzmc.world.*
import java.nio.file.Paths
fun structured() {
val request = OptimizerRequest(
input = Paths.get("/path/to/world"),
output = Paths.get("/path/to/out"),
filter = FilterOptions(
inhabitedThresholdSeconds = 600,
removeUnknown = true,
strict = false
),
outputOptions = OutputOptions(
inPlace = false,
zipOutput = true,
force = true,
copyMisc = true
),
progress = ProgressOptions(
interval = 500,
intervalMs = 0,
sink = CallbackProgressSink { e -> println(e) }
),
runtime = RuntimeOptions(parallelism = 2),
hooks = Hooks(
onError = { e -> println("Error: $e") },
reportSink = FileReportSink(Paths.get("/path/to/report.json"), "json")
),
io = IOOptions(
fs = RealFileSystem,
ioFactory = DefaultMcaIOFactory()
)
)
val report = Optimizer.run(request)
println(ReportIO.toJson(report))
}完整示例:
import com.jokerhub.orzmc.world.*;
import java.nio.file.Paths;
public class JavaExample {
public static void main(String[] args) {
OptimizerRequest request = new OptimizerRequest(
Paths.get("/path/to/world"),
Paths.get("/path/to/out"),
new FilterOptions(600, false, false),
new OutputOptions(false, true, true, true),
new ProgressOptions(1000L, 0L, new CallbackProgressSink(e -> System.out.println(e))),
new RuntimeOptions(2),
new Hooks(
e -> System.out.println("Error: " + e),
new FileReportSink(Paths.get("/path/to/report.json"), "json"),
null
),
new IOOptions(RealFileSystem.INSTANCE, new DefaultMcaIOFactory())
);
OptimizeReport report = Optimizer.run(request);
System.out.println(ReportIO.toJson(report));
}
}最小化示例:
import com.jokerhub.orzmc.world.*;
import java.nio.file.Paths;
public class JavaMinimal {
public static void main(String[] args) {
OptimizerRequest request = new OptimizerRequest(
Paths.get("/path/to/world"),
Paths.get("/path/to/out"),
new FilterOptions(),
new OutputOptions(),
new ProgressOptions(),
new RuntimeOptions(),
new Hooks(),
new IOOptions()
);
OptimizeReport report = Optimizer.run(request);
System.out.println(ReportIO.toJson(report));
}
}reportSink 自动补全示例:
import com.jokerhub.orzmc.world.*;
import java.nio.file.Paths;
public class JavaReportSinkAuto {
public static void main(String[] args) {
OptimizerRequestBuilder builder = new OptimizerRequestBuilder(
Paths.get("/path/to/world"),
Paths.get("/path/to/out")
);
builder.reportFormat = "csv";
builder.reportSink = "/path/to/report";
OptimizeReport report = Optimizer.run(builder.build());
System.out.println(ReportIO.toJson(report));
}
}- input/output → Optimizer.run(input, output) 或 OptimizerRequest(input/output)
- inhabitedThresholdSeconds → inhabitedThresholdSeconds 或 filter.inhabitedThresholdSeconds
- removeUnknown → removeUnknown 或 filter.removeUnknown
- zipOutput → zipOutput 或 outputOptions.zipOutput
- inPlace → inPlace 或 outputOptions.inPlace
- force → force 或 outputOptions.force
- strict → strict 或 filter.strict
- progressInterval → progressInterval 或 progress.interval
- progressIntervalMs → progressIntervalMs 或 progress.intervalMs
- onError → onError { } 或 hooks.onError
- onProgress → progressSink = { } / onProgress { } 或 progress.sink
- parallelism → parallelism 或 runtime.parallelism
- copyMisc → copyMisc 或 outputOptions.copyMisc
- progressSink → progressSink 或 progress.sink
- reportSink → reportSink/reportFormat 或 hooks.reportSink
- fs → fs 或 io.fs
- ioFactory → ioFactory 或 io.ioFactory
- metricsSink → metricsSink 或 hooks.metricsSink
- input/output:输入与输出路径;原地模式下 output 可空
- inhabitedThresholdSeconds/removeUnknown/strict:过滤规则
- zipOutput/inPlace/force/copyMisc:输出策略与杂项复制
- progressInterval/progressIntervalMs:进度回调节流
- progressSink/onProgress:进度回调入口
- parallelism:并行维度处理的线程数
- reportSink/reportFormat:报告输出位置与格式(reportSink 允许 Path/String,省略扩展名时自动补齐)
- fs/ioFactory/metricsSink/onError:IO、指标与错误回调
- 分组配置:filter/outputOptions/progress/runtime/hooks/io
./gradlew :core:test --no-daemon- 测试数据:建议将 Fixtures 目录纳入版本控制(位置:core/src/test/resources/Fixtures),示例文件:
- Fixtures/world/region/r.0.0.mca
- Fixtures/world/data/chunks.dat
- (可选)entities/poi 同名 MCA 文件
- 区块数据压缩:RAW、ZLIB、GZIP、LZ4(LZ4Block)
- LZ4 校验:使用 xxhash seed 0x9747b28c 并按 0x0FFFFFFF 掩码比较,校验失败会抛出错误
- 外部压缩(External*)条目:根据 --remove-unknown 决定是否保留
OrzMCBackup/
├─ app/ # CLI 模块
│ ├─ build.gradle.kts
│ └─ src/main/kotlin/com/jokerhub/orzmc/cli/Main.kt
├─ core/ # 核心库模块
│ ├─ build.gradle.kts
│ └─ src/
│ ├─ main/kotlin/com/jokerhub/orzmc/
│ │ ├─ mca/Reader/Writer/Entry
│ │ ├─ patterns/ChunkPattern/InhabitedTime/List
│ │ └─ world/Optimizer/NbtForceLoader
│ └─ test/resources/Fixtures/ # 建议提交的测试样本
├─ gradle/gradle-wrapper.properties
├─ gradlew / gradlew.bat
├─ settings.gradle.kts
├─ build.gradle.kts
├─ gradle.properties
└─ README.md
-
Gradle Wrapper:固定 8.7(与 Shadow 插件及 Kotlin 1.9.22 兼容)
-
Wrapper 配置位置:gradle-wrapper.properties
-
Wrapper 缓存:使用 GRADLE_USER_HOME(用户主目录)
-
插件版本与仓源统一在根项目声明:build.gradle.kts
-
所有模块的 group 与 version 由根项目统一注入(支持 CI 通过 -Pversion 传入)
-
JDK:默认使用当前环境的 JDK(无需强制 toolchain),已在 macOS aarch64 上验证
- 本地生成可上传 bundle:
./gradlew :core:portalBundle --no-daemon -Pversion=0.1.0 \ -Psigning.keyId=<KEY_ID> -Psigning.password=<PASSWORD> -Psigning.key=<KEY_BASE64_OR_ASCII> # 产物:core/build/portal-bundle.zip
- GitHub Actions 工作流:release-lib.yml
- 触发:push 标签 vX.Y.Z 或手动 workflow_dispatch
- 版本:VERSION=${GITHUB_REF_NAME#v} 或 inputs.version
- JDK:Temurin 21
- 流程:运行 :core:test/:app:test → :core:portalBundle → 生成 sha256 → 校验签名与包 → 上传 Portal
- 上传:Bearer Token(Authorization: Bearer $CENTRAL_TOKEN)
- 仓库 Secrets:
- CENTRAL_TOKEN:Central Portal 用户令牌
- CENTRAL_PORTAL_UPLOAD_URL:Portal 上传端点 URL
- SIGNING_KEY_ID / SIGNING_KEY / SIGNING_PASSWORD:GPG 签名机密(SIGNING_KEY 可为 base64 或 ASCII 装甲)
- SIGNING_KEY 生成示例:
gpg --armor --export-secret-keys <KEY_ID_OR_FINGERPRINT> | base64
- 签名参数说明:
- signing.key:支持 base64 或原始 ASCII 装甲私钥,构建时自动解码
- signing.keyId:支持 8 位短 ID 或 40 位指纹(会归一化为 8 位大写)
- signing.password:若私钥有口令则必填
- 配置位置:core/build.gradle.kts
- POM 信息:
- name:OrzMC Backup Core
- description:Core library for optimizing Minecraft Java worlds
- url:https://github.com/OrzGeeker/OrzMCBackup
- license:Apache License 2.0(https://www.apache.org/licenses/LICENSE-2.0)
- developer:id=orzmc,name=wangzhizhou,email=824219521@qq.com
- scm:
- url:https://github.com/OrzGeeker/OrzMCBackup
- connection:scm:git:https://github.com/OrzGeeker/OrzMCBackup.git
- developerConnection:scm:git:ssh://git@github.com/OrzGeeker/OrzMCBackup.git
- 产物与签名:
- sourcesJar:withSourcesJar
- javadocJar:Dokka 生成后打包
- signing:使用 signing.keyId/signing.key/signing.password(key 支持 base64 或原始 ASCII 装甲)
- 工作流:
- 发布库:release-lib.yml
- 发布 App:release-app.yml
- Apache-2.0;感谢社区与原实现的启发与样例支持