Search in sources :

Example 1 with FluidInDetails

use of mekanism.common.util.MekanismUtils.FluidInDetails in project Mekanism by mekanism.

the class ModuleGeothermalGeneratorUnit method tickServer.

@Override
public void tickServer(IModule<ModuleGeothermalGeneratorUnit> module, PlayerEntity player) {
    IEnergyContainer energyContainer = module.getEnergyContainer();
    if (energyContainer != null && !energyContainer.getNeeded().isZero()) {
        double highestScaledDegrees = 0;
        double legHeight = player.isCrouching() ? 0.6 : 0.7;
        Map<Fluid, FluidInDetails> fluidsIn = MekanismUtils.getFluidsIn(player, bb -> new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, Math.min(bb.minY + legHeight, bb.maxY), bb.maxZ));
        for (Map.Entry<Fluid, FluidInDetails> entry : fluidsIn.entrySet()) {
            FluidInDetails details = entry.getValue();
            double height = details.getMaxHeight();
            if (height < 0.25) {
                // Skip fluids that we are barely submerged in
                continue;
            }
            double temperature = 0;
            List<BlockPos> positions = details.getPositions();
            for (BlockPos position : positions) {
                temperature += entry.getKey().getAttributes().getTemperature(player.level, position);
            }
            // Divide the temperature by how many positions there are in case there is a difference due to the position in the world
            // Strictly speaking we should take the height of the position into account for calculating the average as a "weighted"
            // average, but we don't worry about that as it is highly unlikely the positions will actually have different temperatures,
            // and it would add a bunch of complexity to the calculations to account for it
            temperature /= positions.size();
            if (temperature > HeatAPI.AMBIENT_TEMP) {
                // If the temperature is above the ambient temperature, calculate how many degrees above
                // and factor in how much of the legs are submerged
                double scaledDegrees = (temperature - HeatAPI.AMBIENT_TEMP) * height / legHeight;
                if (scaledDegrees > highestScaledDegrees) {
                    highestScaledDegrees = scaledDegrees;
                }
            }
        }
        if (highestScaledDegrees > 0 || player.isOnFire()) {
            // Note: We compare this against zero as we adjust against ambient before scaling
            if (highestScaledDegrees < 200 && player.isOnFire()) {
                // Treat fire as having a temperature of ~500K, this is on the cooler side of what fire tends to
                // be but should be good enough for factoring in how much a heat adapter would be able to transfer
                highestScaledDegrees = 200;
            }
            // Insert energy
            FloatingLong rate = MekanismGeneratorsConfig.gear.mekaSuitGeothermalChargingRate.get().multiply(module.getInstalledCount()).multiply(highestScaledDegrees);
            energyContainer.insert(rate, Action.EXECUTE, AutomationType.MANUAL);
        }
    }
}
Also used : AxisAlignedBB(net.minecraft.util.math.AxisAlignedBB) FloatingLong(mekanism.api.math.FloatingLong) IEnergyContainer(mekanism.api.energy.IEnergyContainer) FluidInDetails(mekanism.common.util.MekanismUtils.FluidInDetails) Fluid(net.minecraft.fluid.Fluid) BlockPos(net.minecraft.util.math.BlockPos) Map(java.util.Map)

Example 2 with FluidInDetails

use of mekanism.common.util.MekanismUtils.FluidInDetails in project Mekanism by mekanism.

the class ModuleElectrolyticBreathingUnit method tickServer.

@Override
public void tickServer(IModule<ModuleElectrolyticBreathingUnit> module, PlayerEntity player) {
    int productionRate = 0;
    // Check if the mask is underwater
    // Note: Being in water is checked first to ensure that if it is raining and the player is in water
    // they get the full strength production
    float eyeHeight = player.getEyeHeight();
    Map<Fluid, FluidInDetails> fluidsIn = MekanismUtils.getFluidsIn(player, bb -> {
        // Grab the center of the BB as that is where the player is for purposes of what it renders it intersects with
        double centerX = (bb.minX + bb.maxX) / 2;
        double centerZ = (bb.minZ + bb.maxZ) / 2;
        // For the y range check a range of where the mask's breathing unit is based on where the eyes are
        return new AxisAlignedBB(centerX, Math.min(bb.minY + eyeHeight - 0.27, bb.maxY), centerZ, centerX, Math.min(bb.minY + eyeHeight - 0.14, bb.maxY), centerZ);
    });
    if (fluidsIn.entrySet().stream().anyMatch(entry -> entry.getKey().is(FluidTags.WATER) && entry.getValue().getMaxHeight() >= 0.11)) {
        // If the position the bottom of the mask is almost entirely in water set the production rate to our max rate
        // if the mask is only partially in water treat it as not being in it enough to actually function
        productionRate = getMaxRate(module);
    } else if (player.isInRain()) {
        // If the player is not in water but is in rain set the production to half power
        productionRate = getMaxRate(module) / 2;
    }
    if (productionRate > 0) {
        FloatingLong usage = MekanismConfig.general.FROM_H2.get().multiply(2);
        int maxRate = Math.min(productionRate, module.getContainerEnergy().divideToInt(usage));
        long hydrogenUsed = 0;
        GasStack hydrogenStack = MekanismGases.HYDROGEN.getStack(maxRate * 2L);
        ItemStack chestStack = player.getItemBySlot(EquipmentSlotType.CHEST);
        if (checkChestPlate(chestStack)) {
            Optional<IGasHandler> chestCapability = chestStack.getCapability(Capabilities.GAS_HANDLER_CAPABILITY).resolve();
            if (chestCapability.isPresent()) {
                hydrogenUsed = maxRate * 2L - chestCapability.get().insertChemical(hydrogenStack, Action.EXECUTE).getAmount();
                hydrogenStack.shrink(hydrogenUsed);
            }
        }
        if (fillHeld.get()) {
            ItemStack handStack = player.getItemBySlot(EquipmentSlotType.MAINHAND);
            Optional<IGasHandler> handCapability = handStack.getCapability(Capabilities.GAS_HANDLER_CAPABILITY).resolve();
            if (handCapability.isPresent()) {
                hydrogenUsed = maxRate * 2L - handCapability.get().insertChemical(hydrogenStack, Action.EXECUTE).getAmount();
            }
        }
        int oxygenUsed = Math.min(maxRate, player.getMaxAirSupply() - player.getAirSupply());
        long used = Math.max((int) Math.ceil(hydrogenUsed / 2D), oxygenUsed);
        module.useEnergy(player, usage.multiply(used));
        player.setAirSupply(player.getAirSupply() + oxygenUsed);
    }
}
Also used : AxisAlignedBB(net.minecraft.util.math.AxisAlignedBB) FluidInDetails(mekanism.common.util.MekanismUtils.FluidInDetails) Fluid(net.minecraft.fluid.Fluid) FloatingLong(mekanism.api.math.FloatingLong) IGasHandler(mekanism.api.chemical.gas.IGasHandler) GasStack(mekanism.api.chemical.gas.GasStack) ItemStack(net.minecraft.item.ItemStack)

Aggregations

FloatingLong (mekanism.api.math.FloatingLong)2 FluidInDetails (mekanism.common.util.MekanismUtils.FluidInDetails)2 Fluid (net.minecraft.fluid.Fluid)2 AxisAlignedBB (net.minecraft.util.math.AxisAlignedBB)2 Map (java.util.Map)1 GasStack (mekanism.api.chemical.gas.GasStack)1 IGasHandler (mekanism.api.chemical.gas.IGasHandler)1 IEnergyContainer (mekanism.api.energy.IEnergyContainer)1 ItemStack (net.minecraft.item.ItemStack)1 BlockPos (net.minecraft.util.math.BlockPos)1