Skip to content

⏳ 컨티넘: 오프라인 작물 성장 영구 시뮬레이션 엔진

**The Continuum(시공간 연속체)**은 핵심 시뮬레이션 엔진입니다. 바닐라에서는 청크가 언로드되면 성장이 멈추지만, The Continuum은 언로드 시각을 기억하고 청크 복귀 시 경과 시간을 부드럽게 따라잡습니다.


📊 기술 사양 인포박스

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{ ticks}$) 이상 지난 기록은 저장 시 자동 삭제
지원 식물범용 작물, 사탕수수, 선인장, 네더 와트, 코코아, 덩굴, 묘목, 달콤한 열매

⚙️ 컨티넘 작동 원리

┌─────────────────────────────────────────────────────────────┐
│                     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 ticks (~11.37분)틱당 10%3단계
코코아 콩6,825 ticks (~5.68분)20%2단계
달콤한 열매6,825 ticks (~5.68분)20%3단계
덩굴13,650 ticks (~11.37분)10%아래로 번식
묘목95,550 ticks (~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}$$ 주기적 자동 저장(BEFORE_SAVE) 시 30일 이상 지난 데이터는 메모리와 저장 파일에서 자동 삭제됩니다.


💾 청크 영구 저장 및 0-디스크 기록 보장

  1. 분리된 타임스탬프 저장: ContinuumData에 기록되므로 청크 자체의 unsaved 플래그는 false로 유지됩니다.
  2. 읽기 전용 검사: 팔레트만 사전 검사하여 청크를 수정됨 상태로 만들지 않습니다.
  3. 조건부 블록 쓰기: 실제 단계 변화($\Delta \text{age} > 0$)가 있을 때만 setBlock()을 호출하여 디스크 쓰기를 아낍니다($0\text{ 디스크 I/O}$).

See also: 성능 최적화 및 대기열 조절, 작물 레지스트리 및 범용 작물, and 아키텍처 및 Mixin 주입 대상.

Official documentation & web portal for Dasik Igaijinn mods.