⏳ Das Kontinuum: Offline-Pflanzenpersistenz-Engine
Das Kontinuum (The Continuum) ist das Flaggschiff-Simulationssystem. In Vanilla stoppt das Wachstum beim Entladen von Chunks. The Continuum speichert Zeitstempel und simuliert das Offline-Wachstum flüssig beim Neuladen.
📊 Technische Spezifikationen Infobox
| 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) |
| Aktualisierungsbudget | CROPS_PER_TICK = 5 (Gedrosselte globale Warteschlange) |
| Palette Pre-Filter | section.hasOnlyAir() & section.maybeHas(AgrarianCropRules::isCropBlock) |
| Zeitstempel-Obergrenze | Einträge älter als 30 Echtzeittage ($51,840,000\text{ Ticks}$) werden bereinigt |
| Unterstützte Pflanzen | Alle Nutzpflanzen, Zuckerrohr, Kakteen, Netherwarzen, Kakao, Ranken, Setzlinge, Beeren |
⚙️ Funktionsweise des Kontinuums
┌─────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────┘📐 Mathematische Berechnungsformeln
$$\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. Standard-Pflanzen (CropBlock & Mod-Pflanzen)
$$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. Zuckerrohr- und Kakteenhöhe
$$\Delta \text{age} = \left\lfloor \frac{\Delta t_{\text{effective}}}{1365} \right\rfloor$$
3. Intervalle für weitere Pflanzen
| Pflanzenart | Ticks pro Stufe | Wahrscheinlichkeit pro Tick | Max. Stufe |
|---|---|---|---|
| Netherwarze | 13,650 Ticks (~11.37 Min.) | 10% pro Zufallstick | Stufe 3 |
| Kakaobohnen | 6,825 Ticks (~5.68 Min.) | 20% pro Zufallstick | Stufe 2 |
| Süßbeeren | 6,825 Ticks (~5.68 Min.) | 20% pro Zufallstick | Stufe 3 |
| Ranken | 13,650 Ticks (~11.37 Min.) | 10% pro Zufallstick | Wachstum abwärts |
| Setzlinge | 95,550 Ticks (~79.6 Min.) | 1.4% pro Zufallstick | Stufe 2 (Baumwachstum) |
⚡ Leistungsoptimierungen
1. Sub-Chunk Palette-Level Pre-Filtering
Statt alle $98.304$ Blockkoordinaten zu scannen, prüft CropScanner die Paletten jeder $16 \times 16 \times 16$ LevelChunkSection:
section.hasOnlyAir(): Überspringt leere Sub-Chunks in $0.0001\mu\text{s}$.section.maybeHas(AgrarianCropRules::isCropBlock): Prüft Paletten direkt. Gibt es keine Pflanzen, werden 4.096 Blöcke sofort übersprungen. Dadurch werden 85% bis 95% nichtlandwirtschaftlicher Abschnitte ohne Rechenaufwand ignoriert.
2. Bereinigung veralteter Zeitstempel nach 30 Tagen
$$\text{Max Timestamp Age} = 30\text{ days} \times 86,400\text{ s/day} \times 20\text{ ticks/s} = 51,840,000\text{ ticks}$$ Beim regelmäßigen Speichern (BEFORE_SAVE) werden Einträge älter als 30 Tage aus Speicher und Dateien entfernt.
💾 Chunk-Persistenz & Null-Festplatten-Schreibschutz
- Entkoppelte Zeitstempel: Zeitstempel liegen in
ContinuumData, sodassLevelChunk.unsavedauffalsebleibt. - Reine Lese-Scans: Blockprüfungen über Paletten markieren Chunks niemals als modifiziert.
- Bedingtes Schreiben:
setBlock()wird nur bei echtem Fortschritt ($\Delta \text{age} > 0$) aufgerufen ($0\text{ Festplatten-I/O}$).
See also: Leistung und Warteschlangen-Drosselung, Pflanzenregister und universelle Feldfrüchte, and Architektur und Mixin-Ziele.
