
Create-Aeronautics:兼容性 + 漏洞修复
一个针对Sable及其相关问题的修复模组
F**kSable
一个专门修 Sable 的模组 因为 Sable 的作者挖坑不填,我来填
Sable 是个让 Minecraft 方块物理化的模组,想法很酷。但 Rust + Java 的缝合架构嘛……你懂的。这个模组的存在就是为了补那些能让服务器血压直接拉满的洞。
前置
- Sable — 不是可选,毕竟我存在的意义就是擦它的屁股
社区
版本说明
当你发现某个版本标记为 Alpha(例如 v1.0.0-alpha.1),那大概是一个存在已知问题但未被下架的版本。Alpha 版本可能包含未完成的功能、已知的崩溃风险或性能问题,主要用于早期测试和反馈收集。
但请注意:Alpha 也包含 Beta 版本 —— 实际上某些 Beta 反而比 Alpha 更稳定。版本号只是个标签,不代表一切。
详细信息以 GitHub Releases 为准 —— 每个版本的发布说明都会清楚列出已知问题、适用范围和建议。不要只看版本号,看发布说明。
生产环境请优先选择经过充分测试的版本。如果你在 Alpha/Beta 版本中遇到了问题,欢迎到 Discord 反馈,但请理解——测试版就是测试版,崩了别意外。
修复项
默认全开,可通过配置文件单独关闭。依赖其他模组的修复项,缺模组会自动禁用。
Sable 核心修复
| 修复项 | 描述 |
|---|---|
async-save |
SubLevel 保存操作重定向到异步 I/O 线程,防止保存时服务器冻结。Sable 的 Rust 原生层在主线程做同步 I/O —— 稍微大点的物理结构就能把整个服务器卡死。 |
panic-guard |
调用 Rust 原生代码前加安全检查,防止 Rust 侧 panic 把整个 JVM 带走。是的,Rust panic 会直接弄死 Java 进程,没有任何优雅处理。 |
write-flush |
更新存储文件头之前先刷盘,防止崩溃时数据变垃圾。Sable 的存储格式在异常退出后基本就是不可读的废数据。 |
plot-holder-guard |
plot 区块的 holder 不存在时安全跳过方块更新,而不是直接崩溃。竹子长在物理结构旁边?服务器炸。 |
sublevel-entity-guard |
防止 SubLevelInclusiveLevelEntityGetter 遍历异常 AABB 时服务器卡死。EntitySectionStorage 内部数据被并发修改损坏后,实体碰撞检测可能陷入无限循环 —— 一只蝙蝠的碰撞查询就能卡死服务器 60 秒以上。 |
command-block-sublevel-fix |
禁止命令方块(及其变体)被放到物理化结构上。原版只禁止直接物理化命令方块,但你可以先放方块再物理化 —— 显然不是预期行为。 |
player-position-guard |
玩家坐标超出世界边界时自动拉回,防止 SubLevel 物理把玩家扔出世界导致崩溃。Y 轴上限扩展至原版 +1000 格。 |
light-engine-bounds-guard |
防止 SubLevel 区段超出世界高度限制时光照引擎崩溃。 |
physics-ticket-guard |
防止 PhysicsChunkTicketManager 导致 DistanceManager 内部状态损坏(ArrayIndexOutOfBoundsException)。 |
sublevel-volume-limit |
限制单个物理结构最大方块数量(8192,约 16x16x32 体积),防止过大的碰撞体导致 Rapier 原生崩溃。 |
兼容性修复
| 修复项 | 依赖 | 描述 |
|---|---|---|
carryon-compat |
CarryOn | 修 CarryOn 把玩家放到物理化 sub-level 时传送到错误维度并崩溃。Sable 的射线检测返回局部坐标,CarryOn 当全局坐标用,玩家直接被扔进虚空。 |
typewriter-server-fix |
Simulated | 修 Simulated 打字机在专用服务器上崩溃。服务端代码里出现了 net.minecraft.client.gui.screens.Screen —— 这玩意儿在专用服务器上根本不存在。客户端/服务端不分,离谱。 |
aeronautics-server-fix |
Aeronautics | 修航空学 SteamVentBlockEntity 在专用服务器上崩溃。又是客户端类引用,这次是 Minecraft.getInstance()。同一个坑踩两次,真有你的。 |
aeronautics-slime-bearfix |
Aeronautics | 修粘液球粘连结构时可以粘连旋转轴承导致其分离并产生穿模效应。默认关闭 —— 因为很多玩法基于这个 bug。 |
physics-staff-drag-clipfix |
Simulated | 修物理手杖高速拖动物理结构时穿模和飞出世界边界。在 updatePose 中钳制 SubLevel 位置到世界边界内,超出则清零速度。Y 轴上限扩展至原版 +1000 格。默认开启。 |
cna-path-optimization |
Create New Age | 优化 CNA 电网寻路性能。原实现用 ArrayList.contains() 做 BFS visited 检查 —— O(n) 查找,大电网上直接吃掉 18% 的 tick 时间。换 HashSet,O(1)。 |
cna-insert-optimization |
Create New Age | 优化 CNA 能量插入逻辑,减少冗余寻路和消费者满时的提前退出。 |
ctt-concurrent-fix |
Create ThreadedTrains | 修 CTT 和机械动力的并发问题。CTT 把火车 tick 移到工作线程,但只把 manageEntities 调度回主线程,updateContraptionAnchors 还在工作线程跑 —— 主线程读到不一致状态,EntitySectionStorage 里的 AVL 树被搞坏,轻则 NPE,重则整个服务器死循环卡死。 |
effortless-particle-fix |
Effortless, Sable | 修 Effortless 对着 Sable 物理结构操作时客户端崩溃。Sable 射线检测返回 Plot 存储区域的远端坐标,Effortless 用该坐标生成粒子时客户端未加载该区块导致崩溃。修复方式:跳过未加载区块的粒子生成。 |
性能优化
普通优化默认启用,安全无副作用。激进优化默认禁用,效果显著但可能带来行为异常。
普通优化
| 修复项 | 描述 |
|---|---|
spatial-index-query |
queryIntersecting 从线性扫描改为基于区块的空间索引查询,O(n)→O(1)。 |
bbox-object-reuse |
热路径 BoundingBox3d 对象通过 ThreadLocal 池复用,减少 GC 压力。 |
inblock-state-cache |
缓存实体所在方块状态查询结果,避免每 tick 重复遍历。 |
level-accelerator-cache |
启用 LevelAccelerator 的 Long2ObjectMap 区块缓存(原版硬编码关闭),提升碰撞检测区块查找命中率。 |
collision-aabb-prefilter |
SAT 碰撞检测前添加 AABB 预筛,跳过不相交方块的 15 轴 SAT 计算。 |
collision-skip-air |
碰撞检测中空气方块直接返回空 VoxelShape,避免无意义的碰撞形状计算。 |
fastutil-sublevel-maps |
SubLevel 内部 HashMap 替换为 fastutil 原始类型 Map,减少 Map.Entry 对象分配。 |
physics-traversal-merge |
物理管线 tick 中多次 SubLevel 遍历合并为单次遍历,减少迭代开销。 |
network-sync-batch |
网络同步标记优化(原版已有批处理机制,此为补充标记)。 |
激进优化
| 修复项 | 风险 | 描述 |
|---|---|---|
dynamic-collision-substep |
高速实体穿模 | 服务器 TPS 低时动态降低碰撞子步数。 |
skip-far-entity-collision |
远处实体穿模 | 跳过超出阈值的远距离实体碰撞检测。 |
collision-volume-threshold |
大型结构边缘碰撞失效 | 降低小体积方块的碰撞检测精度。 |
dynamic-physics-substep |
物理精度下降 | TPS 低时动态降低物理模拟子步数。 |
reduced-network-sync |
客户端位置不同步 | 降低 SubLevel 状态网络同步频率。 |
skip-noncritical-collision |
掉落物/经验球穿模 | 跳过非关键实体(掉落物等)的碰撞检测。 |
Create 模组优化
| 修复项 | 描述 |
|---|---|
create-kinetic-cache |
缓存 KineticNetwork 应力计算结果,脏标记机制避免重复计算。 |
create-contraption-collision-radius |
缩减装置实体碰撞检测半径,减少远距离碰撞计算。 |
调试命令
| 命令 | 作用 |
|---|---|
/fucksable |
查看所有修复项状态 |
/fucksable <修复项> on/off |
启用/禁用某个修复项 |
/fucksable all on/off |
启用/禁用全部修复项 |
/fucksable default |
恢复所有修复项为默认配置 |
/fucksable fstemp <方块ID> |
遍历已加载区块查找指定方块(包含物理结构上的)—— 其实没啥用,你看命令名也猜得到吧? |
/fucksable fs2temp on <坐标> |
监控指定位置的方块更新,显示完整调用链(点击可复制)—— 和上面那个一样,临时的,没啥大用 |
/fucksable fs2temp off |
停止监控 |
国际化 (i18n)
FuckSable 支持自定义语言包。所有可打印信息(命令反馈、日志等)都可以通过语言文件覆盖。
使用方法
/fucksablelang <语言文件名>
<语言文件名>: 语言文件的名称(不含路径,不含扩展名)
语言文件位于 .minecraft/config/fucksable/lang/(服务端则为 config/fucksable/lang/)。
默认语言包
| 文件名 | 语言 |
|---|---|
zh.yml |
简体中文 |
en.yml |
英文 |
创建自定义语言包
- 进入
config/fucksable/lang/目录 - 复制
en.yml或zh.yml作为模板 - 重命名为你想要的语言文件名(例如
ja.yml、es.yml、fr.yml) - 翻译 YAML 文件中的值(键名不要改)
- 在游戏中执行
/fucksablelang <文件名>切换
注意事项
- FuckSable 的可打印信息不是很多,所有文本加起来也就几十行
- 你完全可以直接丢给 GPT 去翻译,几秒钟搞定
- 切换语言后立即生效,不需要重启服务器
- 如果语言文件格式错误(无效 YAML),会自动回退到默认语言(英文)
示例:自定义语言文件结构
# zh.yml - 简体中文示例
command:
fucksable:
title: "=== FuckSable 修复状态 ==="
fix:
enabled: "✓ %s 已启用"
disabled: "✗ %s 已禁用"
missing_dep: "⚠ %s 已禁用 (缺少依赖: %s)"
invalid_fix: "无效的修复项: %s"
set:
enabled: "已将 %s 设置为 %s"
lang:
switched: "语言已切换至: %s"
file_not_found: "语言文件不存在: %s"
invalid_yml: "语言文件格式错误,已回退至默认语言"
# en.yml - 英文示例
command:
fucksable:
title: "=== FuckSable Fix Status ==="
fix:
enabled: "✓ %s is enabled"
disabled: "✗ %s is disabled"
missing_dep: "⚠ %s is disabled (missing dependency: %s)"
invalid_fix: "Invalid fix: %s"
set:
enabled: "Set %s to %s"
lang:
switched: "Language switched to: %s"
file_not_found: "Language file not found: %s"
invalid_yml: "Invalid YAML format, falling back to default language"
为什么是 All-in-One?
Q: 为什么不写单独的模组逐个修复,而是全部打包在一起?
A: 因为我讨厌为了修复几个问题还要到处找补丁、一个个安装、反复排查冲突。
FuckSable 是全部打包:
- 一个模组,一次安装,所有修复同时生效
- 每一个修复都在真实服务端环境测试过,不是纸上谈兵
- 配置文件可以单独开关,不需要就不开
- 不用记这个 bug 归哪个模组管,一个命令全看见
简单说就是:省事。
吐槽
Sable 的 Rust + Java 架构本身不是问题。问题在于两边几乎都没有错误处理:
- Rust 侧 panic → 直接带走 JVM
- Java 侧对 Rust 返回值校验 ≈ 不存在
- 服务端引用客户端类?这不是边缘 case,是专用服务器一启动就崩的程度
依赖管理也是一坨屎:API 类散落在各种包路径下 —— SubLevelContainerHolder 在 mixinterface.plot 而不是 api.sublevel,JOMLConversion 在 companion.math。你永远猜不到下一个类在哪个包里。
但话说回来,方块物理化这个想法确实很酷。只是希望作者能多花点时间在稳定性上,而不是只追求功能。
附加说明
自动更新走的是中国 IP,而且没有 SSL 保护。
默认是关闭的(除非你自己改了配置)。不要开。需要更新就去 Modrinth 下,防止供应链攻击。
"我暂时没想把它开源,但你们大可信任安全性 —— 毕竟 Modrinth 审核过了对吧?"
现在开源了。
许可证
MIT License - 详见 LICENSE 文件。
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。