Files
MinecraftForge/src/main/java/net/minecraftforge/fluids/BlockFluidFinite.java
T
Lex Manos 53659fca06 Initial update to 1.8, Super beta. Most rendering related hooks are out due to major changes in 1.8.
Some notes:
Almost all int x, int y, int z parameters have been changed to BlockPos class
ForgeDirection has been removed, replaced by net.minecraft.util.EnumFacing.
All FML classes have moved from packet cpw.mods.fml to net.minecraftforge.fml
Fluid Rendering has been disabled for the time being, to be re-evaulated and a test mod created for it.
Minecraft now uses a Model based system for rendering blocks and Items. The intention is to expand the model format to better suit modder's needed once it is evaulated.
As such, The model loaders from Forge have been removed, to be replaced by expanding vanilla's model format.
Metadata has been extracted out in Minecraft to IBlockState, which holds a list of properties instead of magic number metadata. DO NOT listen to the fearmongering, you can do EVERYTHING with block states you could previously with metadata.
Stencil Bits are disabled entirely by for the main Display, Modders must enable and recreate the FrameBuffer if they wish to use Stencil Bits.
2014-11-26 00:00:54 -08:00

245 lines
7.2 KiB
Java

package net.minecraftforge.fluids;
import java.util.Random;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
/**
* This is a cellular-automata based finite fluid block implementation.
*
* It is highly recommended that you use/extend this class for finite fluid blocks.
*
* @author OvermindDL1, KingLemming
*
*/
public class BlockFluidFinite extends BlockFluidBase
{
public BlockFluidFinite(Fluid fluid, Material material)
{
super(fluid, material);
}
@Override
public int getQuantaValue(IBlockAccess world, BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
if (state.getBlock().isAir(world, pos))
{
return 0;
}
if (state.getBlock() != this)
{
return -1;
}
return ((Integer)state.getValue(LEVEL)) + 1;
}
@Override
public boolean canCollideCheck(IBlockState state, boolean fullHit)
{
return fullHit && ((Integer)state.getValue(LEVEL)) == quantaPerBlock - 1;
}
@Override
public int getMaxRenderHeightMeta()
{
return quantaPerBlock - 1;
}
@Override
public void updateTick(World world, BlockPos pos, IBlockState state, Random rand)
{
boolean changed = false;
int quantaRemaining = ((Integer)state.getValue(LEVEL)) + 1;
// Flow vertically if possible
int prevRemaining = quantaRemaining;
quantaRemaining = tryToFlowVerticallyInto(world, pos, quantaRemaining);
if (quantaRemaining < 1)
{
return;
}
else if (quantaRemaining != prevRemaining)
{
changed = true;
if (quantaRemaining == 1)
{
world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2);
return;
}
}
else if (quantaRemaining == 1)
{
return;
}
// Flow out if possible
int lowerthan = quantaRemaining - 1;
int total = quantaRemaining;
int count = 1;
for (EnumFacing side : EnumFacing.Plane.HORIZONTAL)
{
BlockPos off = pos.offset(side);
if (displaceIfPossible(world, off))
world.setBlockToAir(off);
int quanta = getQuantaValueBelow(world, off, lowerthan);
if (quanta >= 0)
{
count++;
total += quanta;
}
}
if (count == 1)
{
if (changed)
{
world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2);
}
return;
}
int each = total / count;
int rem = total % count;
for (EnumFacing side : EnumFacing.Plane.HORIZONTAL)
{
BlockPos off = pos.offset(side);
int quanta = getQuantaValueBelow(world, off, lowerthan);
if (quanta >= 0)
{
int newquanta = each;
if (rem == count || rem > 1 && rand.nextInt(count - rem) != 0)
{
++newquanta;
--rem;
}
if (newquanta != quanta)
{
if (newquanta == 0)
{
world.setBlockToAir(off);
}
else
{
world.setBlockState(off, getDefaultState().withProperty(LEVEL, newquanta - 1), 2);
}
world.scheduleUpdate(off, this, tickRate);
}
--count;
}
}
if (rem > 0)
{
++each;
}
world.setBlockState(pos, state.withProperty(LEVEL, each - 1), 2);
}
public int tryToFlowVerticallyInto(World world, BlockPos pos, int amtToInput)
{
IBlockState myState = world.getBlockState(pos);
BlockPos other = pos.add(0, densityDir, 0);
if (other.getY() < 0 || other.getY() >= world.getHeight())
{
world.setBlockToAir(pos);
return 0;
}
int amt = getQuantaValueBelow(world, other, quantaPerBlock);
if (amt >= 0)
{
amt += amtToInput;
if (amt > quantaPerBlock)
{
world.setBlockState(other, myState.withProperty(LEVEL, quantaPerBlock - 1), 3);
world.scheduleUpdate(other, this, tickRate);
return amt - quantaPerBlock;
}
else if (amt > 0)
{
world.setBlockState(other, myState.withProperty(LEVEL, amt - 1), 3);
world.scheduleUpdate(other, this, tickRate);
world.setBlockToAir(pos);
return 0;
}
return amtToInput;
}
else
{
int density_other = getDensity(world, other);
if (density_other == Integer.MAX_VALUE)
{
if (displaceIfPossible(world, other))
{
world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3);
world.scheduleUpdate(other, this, tickRate);
world.setBlockToAir(pos);
return 0;
}
else
{
return amtToInput;
}
}
if (densityDir < 0)
{
if (density_other < density) // then swap
{
IBlockState state = world.getBlockState(other);
world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3);
world.setBlockState(pos, state, 3);
world.scheduleUpdate(other, this, tickRate);
world.scheduleUpdate(pos, state.getBlock(), state.getBlock().tickRate(world));
return 0;
}
}
else
{
if (density_other > density)
{
IBlockState state = world.getBlockState(other);
world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3);
world.setBlockState(other, state, 3);
world.scheduleUpdate(other, this, tickRate);
world.scheduleUpdate(other, state.getBlock(), state.getBlock().tickRate(world));
return 0;
}
}
return amtToInput;
}
}
/* IFluidBlock */
@Override
public FluidStack drain(World world, BlockPos pos, boolean doDrain)
{
if (doDrain)
{
world.setBlockToAir(pos);
}
return new FluidStack(getFluid(),
MathHelper.floor_float(getQuantaPercentage(world, pos) * FluidContainerRegistry.BUCKET_VOLUME));
}
@Override
public boolean canDrain(World world, BlockPos pos)
{
return true;
}
}