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.