⏳ The Continuum: Mesin Persistensi Pertumbuhan Offline
The Continuum adalah mesin simulasi andalan. Di vanilla, pertumbuhan terhenti saat chunk di-unload. The Continuum mengatasi ini dengan menyimpan waktu unload dan mensimulasikan pertumbuhan offline secara mulus saat chunk dibuka kembali.
📊 Infobox Spesifikasi Teknis
| Component | Specification |
|---|---|
| Engine Class | net.instantgratification.agrarianreform.continuum.ContinuumManager |
| Data Handler | net.instantgratification.agrarianreform.continuum.ContinuumData |
| Scanner Helper | net.instantgratification.agrarianreform.continuum.CropScanner |
| Saved Data ID | agrarian_reform_continuum (Dimension-scoped SavedDataType) |
| Batas Per Tick | CROPS_PER_TICK = 5 (Antrean global halus tanpa lag) |
| Palette Pre-Filter | section.hasOnlyAir() & section.maybeHas(AgrarianCropRules::isCropBlock) |
| Batas Kedaluwarsa | Catatan lebih dari 30 hari riil ($51,840,000\text{ ticks}$) otomatis dihapus saat save |
| Tanaman Didukung | Semua tanaman, tebu, kaktus, nether wart, kakao, sulur, bibit pohon, buah beri |
⚙️ Cara Kerja The Continuum
┌─────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────┘📐 Formula Matematika Simulasi Pertumbuhan
$$\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. Tanaman Standar (CropBlock & tanaman mod)
$$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. Ketinggian Tebu & Kaktus
$$\Delta \text{age} = \left\lfloor \frac{\Delta t_{\text{effective}}}{1365} \right\rfloor$$
3. Interval Tahap Tanaman Lainnya
| Jenis Tanaman | Tick per Tahap | Peluang per Tick | Tahap Maks / Batas |
|---|---|---|---|
| Nether Wart | 13,650 ticks (~11.37 menit) | 10% per random tick | Tahap 3 |
| Biji Kakao | 6,825 ticks (~5.68 menit) | 20% per random tick | Tahap 2 |
| Buah Beri | 6,825 ticks (~5.68 menit) | 20% per random tick | Tahap 3 |
| Sulur | 13,650 ticks (~11.37 menit) | 10% per random tick | Merambat ke bawah |
| Bibit Pohon | 95,550 ticks (~79.6 menit) | 1.4% per random tick | Tahap 2 (Tumbuh jadi pohon) |
⚡ Optimasi Performa
1. Sub-Chunk Palette-Level Pre-Filtering
Daripada memeriksa $98.304$ koordinat blok, CropScanner memeriksa palet tiap bagian $16 \times 16 \times 16$ LevelChunkSection:
section.hasOnlyAir(): Melewati sub-chunk kosong dalam $0.0001\mu\text{s}$.section.maybeHas(AgrarianCropRules::isCropBlock): Memeriksa array palet. Jika tidak ada tanaman, 4.096 blok langsung dilewati. Ini mengabaikan 85% hingga 95% sub-chunk non-pertanian tanpa membebani server.
2. Pembersihan Catatan Lebih dari 30 Hari
$$\text{Max Timestamp Age} = 30\text{ days} \times 86,400\text{ s/day} \times 20\text{ ticks/s} = 51,840,000\text{ ticks}$$ Saat autosave berkala (BEFORE_SAVE), data yang lebih lama dari 30 hari nyata langsung dibersihkan dari memori.
💾 Persistensi Chunk & Nol Penulisan Disk
- Waktu Terpisah Aman: Waktu dicatat di
ContinuumData, menjagaLevelChunk.unsavedtetapfalse. - Pemindaian Hanya-Baca: Memeriksa palet tanpa mengubah status chunk.
- Penulisan Bersyarat:
level.setBlock()hanya dipanggil bila tanaman benar-benar tumbuh ($\Delta \text{age} > 0$), menghemat harddisk ($0\text{ Disk I/O}$).
See also: Performa & Pembatasan Antrean, Registri Tanaman & Tanaman Universal, and Arsitektur & Target Mixin.
