Aeronautics Display Link Fix [ADLF]
航空学显示链接器修复 [ADLF]
中文
简介
修复 Create: Aeronautics(机械动力航空学)中显示链接器(Display Link)在物理化/反物理化后 TargetOffset 被损坏的问题。覆盖所有场景:无论告示牌在飞行器上、在地面、还是在另一飞行器上。
问题根源
Sable 物理化时通过 saveWithFullMetadata / loadWithComponents 搬运方块实体。
物理化空间中,DisplayLink 的 target() 方法使用物理化空间坐标计算相对偏移:
offset = 告示牌物理化坐标 - DisplayLink物理化坐标
→ 产生巨大异常值(如 -20481038)
这个损坏的偏移被持久化到 NBT 中,反物理化后带回真实世界,导致 DisplayLink 无法正确寻址告示牌。
修复原理
通过 Mixin 注入 Sable 的 SubLevelAssemblyHelper.moveBlocks():
- Phase 1(
loadWithComponents之前):捕获所有正在移动的 DisplayLink 的原始 TargetOffset, 并预计算正确的旋转结果correctedOffset = originalOffset.rotate(rot) - Phase 2(
moveBlocksTAIL):无条件将每个 DisplayLink 的 TargetOffset 恢复为正确值
不再需要 Case 3 检测——任何被物理化的 DisplayLink 都要保护。
特性
- ✅ 全面覆盖:修复所有场景(DL 在飞行器上,告示牌在任意位置)
- ✅ 旋转感知:正确应用 Sable 装配旋转变换
- ✅ 零误判:无 Case 1/2/3 分类,无条件修复
- ✅ 高性能:只处理 DisplayLink 本身,与结构大小无关
- ✅ 可配置日志:
adlf-common.toml中debug = true开启详细追踪
版本历史
| 版本 | 说明 |
|---|---|
| v1.3 | 全面保护:移除 Case 3 检测,无条件保护所有 DisplayLink |
| v1.2.3 | 大型结构性能优化(O(n²) → O(n)) |
| v1.2 | 旋转感知偏移修正 + 配置文件 |
| v1.1 | 初始修复:双层 Case 3 判定 |
构建
# 前置条件:JDK 21
git clone <repo>
cd Aeronautics-display-link-fix
./gradlew build
# jar 输出:build/libs/aeronautics_display_link_fix-<version>.jar
依赖
- Minecraft 1.21.1 + NeoForge 21.1.233
- Create 6.0.10
- Sable 1.2.2
- Create: Simulated 1.2.1
- Create: Aeronautics 1.2.1
注意事项
- 🧠 本项目由 AI 辅助编写,代码结构和实现细节由 AI 辅助生成。
- 🔧 由于作者不保证持续维护,后续版本兼容性可能滞后。
- 🏢 Create / Sable / Aeronautics 官方未来可能会在架构层面修复此 Bug, 届时本 Mod 将不再需要。请关注官方更新日志。
English
Overview
Fixes a bug in Create: Aeronautics where the Display Link's TargetOffset gets
corrupted during physics assembly/disassembly. Covers all scenarios: regardless
of whether the target sign is on the same contraption, on the ground, or on a
different contraption.
Root Cause
During physics assembly, Sable moves block entities via
saveWithFullMetadata / loadWithComponents. In the physics sublevel space,
the DisplayLink's target() method computes its relative offset using sublevel
coordinates:
offset = signSublevelPos - DLSublevelPos
→ huge garbage value (e.g. -20481038)
This corrupted offset gets persisted in NBT and carried back to the real world after disassembly, breaking the DisplayLink's targeting.
How It Works
A Mixin injects into Sable's SubLevelAssemblyHelper.moveBlocks():
- Phase 1 (before
loadWithComponents): Captures the original TargetOffset of every moving DisplayLink and pre-computes the correct rotated value:correctedOffset = originalOffset.rotate(rot) - Phase 2 (
moveBlocksTAIL): Unconditionally restores each DisplayLink's TargetOffset to the correct value
No more Case 3 detection — every DisplayLink being moved needs protection.
Features
- ✅ Universal coverage: Fixes all scenarios (DL on contraption, sign anywhere)
- ✅ Rotation-aware: Correctly applies Sable's assembly rotation transforms
- ✅ Zero false positives: No Case 1/2/3 classification, unconditional fix
- ✅ High performance: Only processes DisplayLinks themselves, O(1) w.r.t. structure size
- ✅ Configurable logging: Toggle
debug = trueinadlf-common.tomlfor detailed tracing
Version History
| Version | Description |
|---|---|
| v1.3 | Universal protection: removed Case 3 detection, protect all DisplayLinks unconditionally |
| v1.2.3 | Large structure performance optimization (O(n²) → O(n)) |
| v1.2 | Rotation-aware offset correction + config file |
| v1.1 | Initial fix: two-layer Case 3 detection |
Build
# Prerequisites: JDK 21
git clone <repo>
cd Aeronautics-display-link-fix
./gradlew build
# Output: build/libs/aeronautics_display_link_fix-<version>.jar
Dependencies
- Minecraft 1.21.1 + NeoForge 21.1.233
- Create 6.0.10
- Sable 1.2.2
- Create: Simulated 1.2.1
- Create: Aeronautics 1.2.1
Notes
- 🧠 This mod was developed with AI assistance — some of the code structure and implementation details were AI-generated.
- 🔧 The author does not guarantee ongoing maintenance. Future version compatibility may lag behind.
- 🏢 Create / Sable / Aeronautics may fix this bug at the architecture level in the future, at which point this mod will no longer be needed. Please check official changelogs.
How to Install Aeronautics Display Link Fix (Mod)
Aeronautics Display Link Fix by FQO3 is verified for Neoforge across Minecraft versions 1.21.1 (latest release: v1.3, file size: 10 KB). Follow the steps below to install it safely from ModCraft.tv:
- Click the Download button above and select your Minecraft version (1.21.1) and platform (Neoforge).
- Make sure you have the compatible loader or environment installed for Neoforge.
- Move the downloaded Aeronautics Display Link Fix file into your Minecraft
.minecraft/modsfolder and launch the game.
All Versions
+ Add Version### 修复
- 修复所有场景下 TargetOffset 损坏问题**:此前的修复仅针对 Case 3(DL 和目标告示牌在同一结构上),但现在发现即使是 Case 1/2(DL 在结构中但告示牌不在),DisplayLink 的 TargetOffset 也会在 Sable 物理化/反物理化过程中被损坏。
- 根本原因:物理化后 DL 的
target()方法使用物理化空间坐标重新计算 offset=告示牌物理化位置-DL物理化位置,产生巨大异常值并持久化 - 移除 Case 3 检测**:不再需要 HashSet 预处理器或复杂的 Case 3 判定逻辑。所有被物理化的 DisplayLink 都需要保护。
### 更改
- 简化架构:仅用一个 ThreadLocal
DL_LIST存储 (原始坐标, 新坐标, 修正后 offset) 三元组 - Phase 1 在
loadWithComponents之前保存所有 DisplayLink 的原始 TargetOffset 及旋转变换 - Phase 2 在 TAIL 无条件恢复所有 DisplayLink 的正确 TargetOffset
BLOCKSET_CACHE、LIST_NEWPOS、LIST_OFFSETThreadLocal 全部移除
### 性能
- O(1) 无**:无需遍历方块列表或构造 HashSet,只处理 DisplayLink 本身
- 对任意规模和任意数量 DisplayLink 的结构保持恒定开销
### 新增
- 旋转感知 TargetOffset 计算**:Phase 2 现在使用
transform.apply(oldTargetAbsolute)独立计算目标方块的正确新位置,然后correctedOffset = newTarget - newDLPos,正确处理 Sable 旋转装配 - 配置文件**:
adlf-common.toml新增debug开关(默认false),无需重启即可切换详细日志 - 条件日志**:生产模式仅输出错误日志;开启
debug = true后输出完整的 Case 3 检测和修复追踪
### 更改
- 主 mod 入口从
Aeronautics_display_link_fix.java迁移至ADLFMod.java,使用 NeoForgeModContainer注册配置 - 配置类从
Config.java(仅 enabled 字段)迁移至AdlfConfig.java(debug 开关 + 完整 spec builder) - Mixin ThreadLocal 从
LIST_NEWPOS改为LIST_BLOCKPOS(保存原始block而非 tag 中的 newPos),用于 Phase 2 计算 - 日志调用全部切换为条件包装器
logDebug()/logError(),默认不产生信息输出
### 移除
- 旧版
Config.java(已被AdlfConfig替代) LIST_DEBUGThreadLocal(冗余,debug 日志由条件开关控制)- 不再需要
newPosFromTag读取(Phase 2 自行计算新位置)
### 修复
- 修复 Case 3:当显示链接器(Display Link)与告示牌在同一飞行器上同步物理化/反物理化时,TargetOffset 被错误变换为世界坐标级大偏移的问题
- 采用双层判定逻辑,同时覆盖正向(方块→物理化)和反向(物理化→方块)组装方向
- 避免误判正常的 Case 1(告示牌在地面)和 Case 2(告示牌在另一飞行器)场景
### 技术细节
- TargetOffset 读取方式从
@Local字节码索引改为从 NBT tag 直接读取(tag.getInt("x/y/z")),消除编译差异风险 - 移除 Mixin 内部类
SavedCase3,改用三组平行ThreadLocal列表,避免 Mixin 包隔离限制导致IllegalClassLoadError - 修正
registryAccess从源世界改为目标世界(dest.registryAccess())
## v1.1 - Two-Layer Detection Fix
### Fixed
- Fixed Case 3: DisplayLink's TargetOffset was incorrectly transformed into world-scale coordinates when the DisplayLink and its sign are on the same contraption
- Two-layer detection covers both forward (blocks→physics) and reverse (physics→blocks) assembly directions
- Correctly excludes normal Case 1 (sign on ground) and Case 2 (sign on different contraption) scenarios
### Technical
- TargetOffset now read from NBT tag directly (
tag.getInt("x/y/z")) instead of@Localbytecode indexing - Removed inner class
SavedCase3, replaced with three parallelThreadLocallists to avoid Mixin package isolationIllegalClassLoadError - Fixed
registryAccessfrom source level to destination level (dest.registryAccess())