use of net.dries007.tfc.common.blockentities.FarmlandBlockEntity in project TerraFirmaCraft by TerraFirmaCraft.
the class CropHelpers method growthTickStep.
public static boolean growthTickStep(Level level, BlockPos pos, BlockState state, Random random, long fromTick, long toTick, CropBlockEntity crop) {
// Calculate invariants
final ICalendar calendar = Calendars.get(level);
final BlockPos sourcePos = pos.below();
final int hydration = FarmlandBlock.getHydration(level, sourcePos);
final float startTemperature = Climate.getTemperature(level, pos, calendar, Calendars.SERVER.ticksToCalendarTicks(fromTick));
final float endTemperature = Climate.getTemperature(level, pos, calendar, Calendars.SERVER.ticksToCalendarTicks(toTick));
final long tickDelta = toTick - fromTick;
final ICropBlock cropBlock = (ICropBlock) state.getBlock();
final ClimateRange range = cropBlock.getClimateRange();
final boolean growing = checkClimate(range, hydration, startTemperature, endTemperature, false);
final boolean healthy = growing || checkClimate(range, hydration, startTemperature, endTemperature, true);
// Nutrients are consumed first, since they are independent of growth or health.
// As long as the crop exists it consumes nutrients.
final FarmlandBlockEntity farmland = level.getBlockEntity(sourcePos, TFCBlockEntities.FARMLAND.get()).orElse(null);
final FarmlandBlockEntity.NutrientType primaryNutrient = cropBlock.getPrimaryNutrient();
float nutrientsAvailable = 0, nutrientsRequired = NUTRIENT_CONSUMPTION * tickDelta, nutrientsConsumed = 0;
if (farmland != null) {
nutrientsAvailable = farmland.getNutrient(primaryNutrient);
nutrientsConsumed = farmland.consumeNutrientAndResupplyOthers(primaryNutrient, nutrientsRequired);
}
// Total growth is based on the ticks and the nutrients consumed. It is then allocated to actual growth or expiry based on other factors.
float totalGrowthDelta = Helpers.uniform(random, 0.9f, 1.1f) * tickDelta * GROWTH_FACTOR + nutrientsConsumed * NUTRIENT_GROWTH_FACTOR;
final float initialGrowth = crop.getGrowth();
float growth = initialGrowth, expiry = crop.getExpiry(), actualYield = crop.getYield();
final float growthLimit = cropBlock.getGrowthLimit(level, pos, state);
if (totalGrowthDelta > 0 && growing && growth < growthLimit) {
// Allocate to growth
final float delta = Math.min(totalGrowthDelta, growthLimit - growth);
growth += delta;
totalGrowthDelta -= delta;
}
if (totalGrowthDelta > 0) {
// Allocate remaining growth to expiry
final float delta = Math.min(totalGrowthDelta, EXPIRY_LIMIT - expiry);
expiry += delta;
totalGrowthDelta -= delta;
}
// Calculate yield, which depends both on a flat rate per growth, and on the nutrient satisfaction, which is a measure of nutrient consumption over the growth time.
final float growthDelta = growth - initialGrowth;
final float nutrientSatisfaction;
if (growthDelta <= 0 || nutrientsRequired <= 0) {
// Either condition causes the below formula to result in NaN
nutrientSatisfaction = 1;
} else {
nutrientSatisfaction = Math.min(1, (totalGrowthDelta / growthDelta) * (nutrientsAvailable / nutrientsRequired));
}
actualYield += growthDelta * Helpers.lerp(nutrientSatisfaction, YIELD_MIN, YIELD_LIMIT);
// Check if the crop should've expired.
if (expiry >= EXPIRY_LIMIT || !healthy) {
// Lenient here - instead of assuming it expired at the start of the duration, we assume at the end. Including growth during this period.
cropBlock.die(level, pos, state, growth >= 1);
return false;
}
crop.setGrowth(growth);
crop.setYield(actualYield);
crop.setExpiry(expiry);
crop.setLastUpdateTick(calendar.getTicks());
return true;
}
Aggregations