Search in sources :

Example 1 with FarmlandBlockEntity

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;
}
Also used : ClimateRange(net.dries007.tfc.util.climate.ClimateRange) FarmlandBlockEntity(net.dries007.tfc.common.blockentities.FarmlandBlockEntity) ICalendar(net.dries007.tfc.util.calendar.ICalendar) BlockPos(net.minecraft.core.BlockPos)

Aggregations

FarmlandBlockEntity (net.dries007.tfc.common.blockentities.FarmlandBlockEntity)1 ICalendar (net.dries007.tfc.util.calendar.ICalendar)1 ClimateRange (net.dries007.tfc.util.climate.ClimateRange)1 BlockPos (net.minecraft.core.BlockPos)1