package pneumaticCraft.common.heat.behaviour; import java.util.HashSet; import java.util.Set; import java.util.Stack; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import pneumaticCraft.common.heat.HeatExchangerManager; import pneumaticCraft.common.network.NetworkHandler; import pneumaticCraft.common.network.PacketPlaySound; import pneumaticCraft.common.network.PacketSpawnParticle; import pneumaticCraft.common.util.FluidUtils; public abstract class HeatBehaviourLiquidTransition extends HeatBehaviourLiquid{ private double extractedHeat; private double maxExchangedHeat; private int fluidTemp = -1; @Override public boolean isApplicable(){ Fluid fluid = getFluid(); return fluid != null && fluid.getTemperature() >= getMinFluidTemp() && fluid.getTemperature() <= getMaxFluidTemp(); } protected abstract int getMinFluidTemp(); protected abstract int getMaxFluidTemp(); protected abstract int getMaxExchangedHeat(); protected abstract Block getTransitionedSourceBlock(); protected abstract Block getTransitionedFlowingBlock(); protected abstract boolean transitionOnTooMuchExtraction(); @Override public void update(){ if(fluidTemp == -1) { fluidTemp = getFluid().getTemperature(); maxExchangedHeat = getMaxExchangedHeat() * (HeatExchangerManager.FLUID_RESISTANCE + getHeatExchanger().getThermalResistance()); } extractedHeat += fluidTemp - getHeatExchanger().getTemperature(); if(transitionOnTooMuchExtraction() ? extractedHeat > maxExchangedHeat : extractedHeat < -maxExchangedHeat) { transformSourceBlock(getTransitionedSourceBlock(), getTransitionedFlowingBlock()); extractedHeat -= maxExchangedHeat; } } @Override public void writeToNBT(NBTTagCompound tag){ super.writeToNBT(tag); tag.setDouble("extractedHeat", extractedHeat); } @Override public void readFromNBT(NBTTagCompound tag){ super.readFromNBT(tag); extractedHeat = tag.getDouble("extractedHeat"); } protected void transformSourceBlock(Block turningBlockSource, Block turningBlockFlowing){ if(FluidUtils.isSourceBlock(getWorld(), getX(), getY(), getZ())) { getWorld().setBlock(getX(), getY(), getZ(), turningBlockSource); onLiquidTransition(getX(), getY(), getZ()); } else { Set<ChunkPosition> traversed = new HashSet<ChunkPosition>(); Stack<ChunkPosition> pending = new Stack<ChunkPosition>(); pending.push(new ChunkPosition(getX(), getY(), getZ())); while(!pending.isEmpty()) { ChunkPosition pos = pending.pop(); for(ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { ChunkPosition newPos = new ChunkPosition(pos.chunkPosX + d.offsetX, pos.chunkPosY + d.offsetY, pos.chunkPosZ + d.offsetZ); Block checkingBlock = getWorld().getBlock(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ); if((checkingBlock == getBlock() || getBlock() == Blocks.flowing_water && checkingBlock == Blocks.water || getBlock() == Blocks.flowing_lava && checkingBlock == Blocks.lava) && traversed.add(newPos)) { if(FluidUtils.isSourceBlock(getWorld(), newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ)) { getWorld().setBlock(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ, turningBlockSource); onLiquidTransition(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ); return; } else { getWorld().setBlock(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ, turningBlockFlowing); onLiquidTransition(newPos.chunkPosX, newPos.chunkPosY, newPos.chunkPosZ); pending.push(newPos); } } } } } } protected void onLiquidTransition(int x, int y, int z){ NetworkHandler.sendToAllAround(new PacketPlaySound("random.fizz", x + 0.5, y + 0.5, z + 0.5, 0.5F, 2.6F + (getWorld().rand.nextFloat() - getWorld().rand.nextFloat()) * 0.8F, true), getWorld()); for(int i = 0; i < 8; i++) { double randX = x + getWorld().rand.nextDouble(); double randZ = z + getWorld().rand.nextDouble(); NetworkHandler.sendToAllAround(new PacketSpawnParticle("largesmoke", randX, y + 1, randZ, 0, 0, 0), getWorld()); } } }