Skip to content

⏳ 时空连续体:作物离线持久化生长模拟引擎

时空连续体(The Continuum) 是 Agrarian Reform 的核心仿真引擎。在原版 Minecraft 中,区块卸载或服务器关闭的瞬间作物生长便完全停滞。时空连续体 通过持久化区块卸载时间戳并在重新加载时平滑追赶真实流逝时间,完美弥补了这一断层,且绝不引发瞬间卡顿。


📊 核心技术特性信息框

ComponentSpecification
Engine Classnet.instantgratification.agrarianreform.continuum.ContinuumManager
Data Handlernet.instantgratification.agrarianreform.continuum.ContinuumData
Scanner Helpernet.instantgratification.agrarianreform.continuum.CropScanner
Saved Data IDagrarian_reform_continuum (Dimension-scoped SavedDataType)
更新限流额度CROPS_PER_TICK = 5(全局无锁队列平滑节流)
Palette Pre-Filtersection.hasOnlyAir() & section.maybeHas(AgrarianCropRules::isCropBlock)
陈旧记录上限超过 30 个真实日($51,840,000\text{ 刻}$)在存档时自动清理
支持植物类型全能通用作物、甘蔗、仙人掌、下界疣、可可豆、藤蔓、树苗、甜浆果

⚙️ 时空连续体运行机制

┌─────────────────────────────────────────────────────────────┐
│                     CHUNK UNLOAD EVENT                      │
│ ServerChunkEvents.CHUNK_UNLOAD records server game time pos │
│ Saved to world storage via ContinuumData (SavedDataType)    │
└──────────────────────────────┬──────────────────────────────┘

                               ▼ (Offline / World Unloaded Time Delta)
┌──────────────────────────────┴──────────────────────────────┐
│                      CHUNK LOAD EVENT                       │
│ ServerChunkEvents.CHUNK_LOAD retrieves unload timestamp     │
│ Calculates timeDelta = currentTick - unloadTick             │
└──────────────────────────────┬──────────────────────────────┘


┌──────────────────────────────┴──────────────────────────────┐
│             SUB-CHUNK PALETTE-GATED SCANNER                 │
│ CropScanner skips empty air & non-crop sections (O(1))      │
│ Queues matching plants into ConcurrentLinkedQueue            │
└──────────────────────────────┬──────────────────────────────┘


┌──────────────────────────────┴──────────────────────────────┐
│            THROTTLED PER-CROP TICK PROCESSOR                │
│ ServerTickEvents.END_SERVER_TICK processes 5 crops/tick     │
│ Scales delta per-crop via AgrarianCropRules & updates state │
└─────────────────────────────────────────────────────────────┘

📐 数学补算模型与公式

$$\Delta t_{\text{effective}} = \begin{cases} 0 & \text{if } M_{\text{crop}} \le 0 \ \left\lfloor \frac{\Delta t \cdot M_{\text{crop}}}{100} \right\rfloor & \text{if } M_{\text{crop}} > 0 \end{cases}$$

1. 标准作物 (CropBlock 与模组作物)

$$S = \text{CropScanner.getSpeed}(\text{crop}, \text{level}, \text{pos})$$ $$T_{\text{stage}} = \left( \frac{25.0}{S} + 1.0 \right) \cdot \frac{4096.0}{3.0}$$ $$\Delta \text{age} = \left\lfloor \frac{\Delta t_{\text{effective}}}{T_{\text{stage}}} \right\rfloor$$

2. 甘蔗与仙人掌柱状高度

$$\Delta \text{age} = \left\lfloor \frac{\Delta t_{\text{effective}}}{1365} \right\rfloor$$

3. 其他植物阶段时间间隔

植物类型单阶段刻数随机刻基础概率最大阶段 / 限制
下界疣13,650 刻 (~11.37 分钟)每随机刻 10%阶段 3
可可豆6,825 刻 (~5.68 分钟)每随机刻 20%阶段 2
甜浆果丛6,825 刻 (~5.68 分钟)每随机刻 20%阶段 3
藤蔓13,650 刻 (~11.37 分钟)每随机刻 10%向下蔓延生长
树苗95,550 刻 (~79.6 分钟)每随机刻 1.4%阶段 2 (触发长成大树)

⚡ 极限性能优化策略

1. Sub-Chunk Palette-Level Pre-Filtering

与遍历已加载区块内全部 $98,304$ 个三维坐标不同,CropScanner 对每个 $16 \times 16 \times 16$ 的 LevelChunkSection 实施子区块调色板过滤:

  1. section.hasOnlyAir():在 $0.0001\mu\text{s}$ 内瞬间跳过全空子区块。
  2. section.maybeHas(AgrarianCropRules::isCropBlock):直接检索调色板数组。若不含农作物方块,4,096 格的大区域即刻跳过。 这一优化在零体素遍历开销下直接排除了 85% 至 95% 的非农业子区块。

2. 30 天过期时间戳自动清理

$$\text{Max Timestamp Age} = 30\text{ days} \times 86,400\text{ s/day} \times 20\text{ ticks/s} = 51,840,000\text{ ticks}$$ 在周期性自动保存时(ServerLifecycleEvents.BEFORE_SAVE),超过 30 天真实时间的记录将自动从内存和文件中清除。


💾 区块持久化与零磁盘写入保证

  1. 世界级解耦时间戳:区块卸载时间戳保存在独立的 ContinuumData 中,使区块本身的 LevelChunk.unsaved 依然保持 false
  2. 100% 只读区块加载检测:基于调色板预过滤检查方块,绝不污染区块脏状态。
  3. 条件式方块状态写入仅当作物产生实际成长($\Delta \text{age} > 0$)时才调用 level.setBlock(),避免多余的磁盘 I/O($0\text{ 磁盘写入}$)。

See also: 性能优化与队列节流, 作物注册表与通用作物, and 架构设计与 Mixin 注入参考.

Official documentation & web portal for Dasik Igaijinn mods.