⚡ 效能最佳化與佇列節流引擎
Agrarian Reform 專為高乘載伺服器打造,即使面對超大型農業農場也不會造成瞬卡、看門狗超時或 TPS 下降。
📊 效能技術指標資訊框
| Property | Value |
|---|---|
| Global Throttling Budget | CROPS_PER_TICK = 5 |
| Queue Implementation | java.util.concurrent.ConcurrentLinkedQueue |
| Sub-Chunk Palette Filter | hasOnlyAir() & maybeHas(AgrarianCropRules::isCropBlock) |
| 水分搜尋機制 | 柴比雪夫同心環方塊掃描 ($r=1 \to \text{maxRange}$,近水源極速判定) |
| 鞋子最佳化防抖 | 赤足快速判斷 ($0.0001\mu\text{s}$,跳過耗時的附魔檢查) |
| 診斷日誌機制 | 靜態 SLF4J 記錄器,受暫態遊戲規則 agrarian_reform:debug_mode 控管 |
🧠 架構設計與快速略過流水線
┌─────────────────────────────────────────────────────────────┐
│ CHUNK LOAD SCAN EVENT │
│ Palette Pre-Filter: section.hasOnlyAir() & maybeHas() │
│ Rejects 85%+ empty non-crop sub-chunks in O(1) time │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────────────┴──────────────────────────────┐
│ ConcurrentLinkedQueue<CropUpdateTask> │
│ Lock-free thread-safe task buffer │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────────────┴──────────────────────────────┐
│ ServerTickEvents.END_SERVER_TICK │
│ Polls at most 5 tasks per tick │
│ Updates block states smoothly across consecutive game ticks │
└─────────────────────────────────────────────────────────────┘為什麼每刻處理 5 處作物?
當玩家在離開含有 10,000 處作物的農場 24 小時後重返,若在單一刻內同時觸發 10,000 次方塊更新,將導致伺服器產生超過 1000ms 的嚴重凍結。
透過無鎖且以每刻 5 處作物的速率分散更新:
- 區塊載入期間伺服器 TPS 依然維持在極穩定的 20 TPS。
- 10,000 處作物在後台平緩經過 2,000 刻(約 100 秒)即可全部計算完畢,完全不影響遊玩體驗。
🏎️ 核心快速略過與演算法最佳化
- 子區塊調色盤極速判斷:不同於逐一檢查區塊內 $98,304$ 個方塊座標,
CropScanner直接讀取子區塊調色盤。若一個 $16 \times 16 \times 16$ 子區塊不含農業方塊,整片區域將在 $0.0001\mu\text{s}$ 內直接略過。 - 柴比雪夫同心環由內向外掃描:耕地水分計算由最近的方形環($r = 1 \to \text{maxRange}$)逐步向外。因多數耕地緊鄰水源($r=1$),在第一層即完成判定,無須遍歷 $17 \times 17$ 格。
- 赤足踩踏防抖:實體接觸耕地時,
GrowthHelper.hasSoftStep()首先檢查腳部裝備是否為空。若為空,直接跳過複雜的 NBT 附魔遍歷。 - 最大成熟期立即中斷:在高倍率生長循環中,一旦作物達到最大成熟度,循環立刻中斷,省去無謂的方塊寫入運算。
💾 零磁碟寫入保障與髒狀態維護
- 唯讀區塊表面掃描:初始載入掃描 100% 為唯讀,絕不呼叫
LevelChunk.setBlockState(),確保區塊內部unsaved旗標維持false。 - 精確方塊寫入:在
ContinuumManager.processCropUpdate中,僅在生長增量 $\Delta \text{age} > 0$ 時才呼叫level.setBlock()。 - 原生零磁碟寫入防護:未改動的區塊維持
unsaved == false,Minecraft 原生ChunkMap.save()會直接跳過 NBT 序列化與磁碟寫入($0\text{ 磁碟寫入開銷}$)。
See also: 時空連續體 (離線生長模擬), 水動力學與灌溉系統, and 架構設計與 Mixin 注入參考.
