Lang: English | 简体中文
这是一个简单的小工具,用于移除 Minecraft Java 版存档中的无用区块,以腾出部分硬盘空间。
-
可以看作是 Java 语言实现的 Thanos。
-
仅支持 Anvil 文件格式(自 Minecraft JE 1.2.1 起)。
-
较好的情况下可以把游戏存档的硬盘占用减少超过 50%。
-
支持用区块坐标、区块坐标范围(支持通配符)配置每个世界的受保护区块,阻止某些区块被移除。
区块存储在 Anvil 文件内,Minecraft Java 版会为每个区块存储一个字段 InhabitedTime,以记录玩家在这个区块内停留的累计时间刻(tick)数。
本工具通过 InhabitedTime 值筛选出玩家几乎没有停留的的区块,以进行移除。其既可以在本地游戏存档上使用,也可以在服务器存档上使用。
玩家只要在某个区块的 生物生成距离详见文档 内,这个区块的
InhabitedTime就会增长。即玩家所在区块的周围区块的InhabitedTime往往也会增长。
-
如果你采用的是 Paper 端,或者是以 Paper 为上游的服务端(比如 Purpur),请不要在 Paper 的世界配置文件中把
fixed-chunk-inhabited-time详见文档 这一项设置为$\ge 0$ 的值,否则区块的InhabitedTime会被固定,从而影响工具功能。 -
如果你的存档是通过模组 / 外部软件编辑得到的,而不是人为建造的,其中的区块的
InhabitedTime值难以预料,这种情况下不建议使用本工具。当然,你也可以配置受保护的区块以防止某些区块被移除。
-
本工具可以对区域区块 Anvil 文件进行原地处理,原地写入每个文件前会进行备份,若写入出错则会自动还原。尽管如此,还是建议时不时对存档做一下手动备份。
- 你应该已经安装了相应版本的 JRE(Java 运行环境),可以参考这个文档。
- 从 Releases 按照你的 Java 版本下载
PotatoPeeler*.jar,找个位置放着即可(比如 Minecraft 服务端根目录)。
你可以在命令行运行此工具程序:
java [jvmOptions...] -jar PotatoPeeler*.jar
[--world-dirs <worldPath1>,<worldPath2>,...]
[--output-dirs <outputWorldPath1>,<outputWorldPath2>,...]
[--server-jar <serverJarPath>]
[--min-inhabited <ticks>]
[--help]
[--cool-down <minutes>]
[--threads-num <number>]
[--max-log-size <size>]
[--retain-log-files <number>]
[--verbose]
[--dry-run]
[--skip-peeler]
[additionalOptions...]| 标志项 | 说明 |
|---|---|
--help |
显示帮助信息 |
--verbose |
往日志中输出详细信息 |
--dry-run |
执行试运行,不会进行任何实际的写入操作,仅用于测试,建议与 --verbose 标志结合使用 |
--skip-peeler |
直接跳过区块处理过程。若指定了 --server-jar 参数,会直接启动 Minecraft 服务端 |
| 参数项 | 默认值 | 说明 |
|---|---|---|
--world-dirs |
用逗号分隔的世界存档路径。 * 比如 /opt/server/world,world_nether,指定了两个世界目录,分别以绝对路径和相对路径的方式。程序会逐个处理这些世界。 |
|
--output-dirs |
用逗号分隔的世界存档输出路径。 * ❗ 如果不指定这一项,将会原地修改文件。 * 如果指定了这一项,指定的路径个数必须和 --world-dirs 的一致。* 如果指定了这一项,处理后的 region 目录会被输出到指定的路径中。* 输出目录会被自动创建。 |
|
--min-inhabited |
0 |
区块的 InhabitedTime 阈值(单位为 tick,20 ticks = 1 秒)。* 某个区块的 InhabitedTime 低于或等于这个值时,若其未受保护见下方,则会被移除。* 比如我想移除玩家总停留时间 100。* 不建议将此值设置为 * 默认值 0 其实已经有不错的效果。 |
--cool-down |
0 |
距离上次区块处理过去多久后才能再次使用本工具(单位为分钟)。 * 注意是自上次所有指定世界的区块处理完成起计时。比如采用了 --skip-peeler 标志跳过了区块处理,就不计入在内。 |
--threads-num |
10 |
采用多少线程并发(多核情况下可能能并行)处理一个世界中的 Anvil 文件。 |
--max-log-size |
2097152 |
单个日志文件的最大大小(字节)。 |
--retain-log-files |
10 |
最多只保留几个日志文件。 |
--server-jar |
指定 Minecraft 服务端 jar 包路径。 * 如果指定了可用的 jar 包,在本工具程序执行完后将会直接在当前 JVM 中运行此 jar 包,启动服务器。 |
|
| jvmOptions | JVM 参数。 * 如果指定了 --server-jar,JVM 参数会被服务端沿用。 |
|
| additionalOptions | 剩余参数。 * 如果指定了 --server-jar,这些参数会被传递给服务端。 |
-
注 1:对于原版存档格式,你可以这样指定各个世界维度:
--world-dirs world,world/DIM1,world/DIM-1。实际上本工具会采用广度优先方式搜索目录下的
region子目录,如果目录中不同层级有多个region目录,最浅层的首个region目录会被采用。 -
注 2:如果不想在命令行写参数,你可以在
PotatoPeeler*.jar的工作目录下建立一个文件potatopeeler.args,把命令行参数全部写入此文件(JVM 参数除外)。仅当命令行中没有指定参数时(JVM 参数除外),本工具才会读取
potatopeeler.args文件。
受保护的区块不会被移除,主要包含以下三类:
- 世界中强制加载的区块(/forceload)。
- 自定义的受保护区块。
- 数据量过大的区块。
你可以在世界维度根目录(也就是和 region 在同一级目录中)下建立一个文本文件 chunks.protected,以指定要在这个世界中保护的区块。
点击查看这个文件所在位置的示例
world
├── DIM-1
│ ├── data
│ │ └── raids_end.dat
│ └── region
│ └── ...
├── DIM1
│ ├── data
│ │ └── raids_end.dat
│ ├── region
│ └── chunks.protected # 末地维度中要保护的区块
├── data
│ └── raids.dat
├── datapacks
├── entities
│ ├── r.-1.-1.mca
│ └── ...
│
├── level.dat
├── level.dat_old
├── chunks.protected # 主世界维度中要保护的区块
├── playerdata
├── region
│ ├── r.-1.-1.mca
│ ├── r.-1.0.mca
│ ├── r.0.-1.mca
│ └── r.0.0.mca
└── session.lock注:非原版服务端可能把 DIM-1, DIM1 这些维度单独存放在其他目录中,比较常见的则是 world_nether/DIM-1,world_the_end/DIM1。
- 一行指定一条规则,可以是形如
x,z的单个区块坐标点,也可以是x1~x2,z1~z2这样的矩形区域。 - 支持通配符
*。(比如*~5,6就可以保护$x \in [-2^{31},5], z = 6$ 这个长条形状区域内的区块。) - 支持以
#开头的单行注释和行内注释。
点击查看文件内容示例
# 保护所有区块,这样的话本工具根本就没法在这个世界维度发挥作用
*,*
*~*,* # 这样写也是一样的
*,*~*
# 保护 x 从 -5 到 5,z = 6 的长条形状区域
-5~5,6
# 保护 x 从 -54 到 14,z 从 7 到 77 的矩形区域
-54 ~ 14 , 7 ~ 77 # 写松散点也没事
# ~ 两边的数字谁大谁小无所谓
1~4, 18~9 # 保护 x 从 1 到 4,z 从 9 到 18 的矩形区域
# 仅保护单个区块
12 , 450所有输出到控制台的日志都会保存在本工具运行目录的 peeler_logs 子目录中。
- 小贴士: 如果你使用了
--verbose选项,产生的日志量可能较大,这时你可以通过--max-log-size或--retain-log-files参数来进行调整以防日志不完整。
# 从指定的三个世界中移除掉玩家总停留时间 <= 5 秒的区块
java -jar PotatoPeeler*.jar --min-inhabited 100 --world-dirs world,world_nether,/opt/server/world_the_end
# 或者可以更简单点,只指定世界路径。默认情况下只移除玩家总停留时间 = 0 秒的区块
java -jar PotatoPeeler*.jar --world-dirs world,world_nether,/opt/server/world_the_end# 从指定的两个世界中移除掉玩家总停留时间 <= 5 秒的区块
# 移除完成后会在当前 JVM 中启动 purpur.jar
# JVM 参数 -Xms1G -Xmx4G 会被沿用
# 其他参数 / 标志 --nogui --forceUpgrade 会被传递给 purpur.jar
java -Xms1G -Xmx4G -jar PotatoPeeler*.jar --min-inhabited 100 --world-dirs world,world_nether --server-jar purpur.jar --nogui --forceUpgrade可以给服务器设置定时重启任务。比如我每天凌晨四点执行重启,但是我又想每 4 天清理一次无用区块,就可以这样写服务器启动脚本:
#!/bin/bash
# 利用 --cool-down 参数配置每次清理完后冷却 5760 分钟才会进行下一次清理,即每 4 天清理一次无用区块
java -Xms1G -Xmx4G -jar PotatoPeeler*.jar --cool-down 5760 --world-dirs world,world_nether --server-jar purpur.jar --noguijava -jar PotatoPeeler*.jar --world-dirs 'C:\Users\Administrator\AppData\Roaming\.minecraft\saves\MyWorld'对于每个世界维度,如果有 chunks.protected 配置文件,程序就会在控制台打印:
Protected chunks from <path of chunks.protected> have been read.
如果
chunks.protected格式错误无法读取,程序会提示错误的行号和部分内容。
如果这个世界中包含被强制加载的区块,将会打印:
Chunk tickets file found, reading force-loaded chunks.
Loaded <num> forced chunks.
点击查看此示例
当没有指定命令行参数时,程序会尝试从 potatopeeler.args 文件中读取参数。
可以把命令行参数(不包括 JVM 参数)全部写入 PotatoPeeler*.jar 工作目录下的 potatopeeler.args 文件。
potatopeeler.args 文件示例如下:
--min-inhabited 100 --world-dirs world,world_nether,world_the_end --server-jar purpur.jar通常把 potatopeeler.args 和 PotatoPeeler*.jar 两个文件放到同一目录下:
Server Root
├── PotatoPeeler-1.0.0.jar # 本工具程序
├── bukkit.yml
├── config
├── plugins
├── potatopeeler.args # PotatoPeeler 参数文件
├── server.properties
├── spigot.yml
├── purpur.jar
├── whitelist.json
├── world
├── world_nether
└── world_the_end然后直接执行 java -jar PotatoPeeler*.jar 即可,命令行参数会自动从 potatopeeler.args 文件中读取。
点击查看此示例
java -jar PotatoPeeler*.jar --world-dirs '/opt/server/world,/opt/server2/world' --output-dirs '/opt/trimmed/world_out_1,/opt/trimmed/world_out_2'- 这是非原地操作,
--world-dirs目录中的文件不会被修改。
处理完成后,/opt/trimmed/world_out_1 和 /opt/trimmed/world_out_2 目录下会生成 region 子目录,里面存放着处理好的区域文件,示例如下:
world_out_1
└── region
├── r.-1.-1.mca
├── r.-1.-2.mca
├── r.-1.-3.mca
└── ...- 如果输出目录下已经有同名文件存在,程序会跳过输出这个区域文件。
# 采用 --dry-run 可以进行试运行,以检查参数和配置是否正确、程序是否能按预料运行。
# 同时可以使用 --verbose 选项来让输出信息更详细
# 以及使用 --max-log-size 参数来保证输出日志能被完整记录
java -jar PotatoPeeler*.jar --world-dirs '/opt/server/world,/opt/server2/world' --dry-run --verbose --max-log-size 10485760- 移除
region目录中 Anvil 文件的区块时应该顺带移除entities和poi目录中相应文件中的部分数据。 - 是否应该处理区块过大时产生的
.mcc文件?
感谢开源开发者们的辛苦工作!
感谢 Minecraft Wiki 的维护者们!
- 区域文件格式 - Minecraft Wiki
- 区块标签存储格式 - Minecraft Wiki
- Java版存档格式 - Minecraft Wiki
- 区块存储格式 - Minecraft Wiki
- 区块标签 - Minecraft Wiki
- NBT 二进制格式 - Minecraft Wiki
- 写得相当清晰的 NBT 格式说明 (这个版本后来被替换了真的太可惜了!)
本项目使用 MIT 许可证,感谢你的使用 o(* ̄▽ ̄*)o。


