mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 00:37:52 +00:00
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.
245 lines
7.2 KiB
Java
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;
|
|
}
|
|
} |