2013-05-23 01:01:19 -04:00
|
|
|
|
2016-06-22 23:49:47 -04:00
|
|
|
/*
|
|
|
|
|
* Minecraft Forge
|
|
|
|
|
* Copyright (c) 2016.
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation version 2.1
|
|
|
|
|
* of the License.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
2013-05-23 01:01:19 -04:00
|
|
|
package net.minecraftforge.fluids;
|
|
|
|
|
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
|
|
|
|
|
import net.minecraft.block.material.Material;
|
2014-11-25 19:56:35 -08:00
|
|
|
import net.minecraft.block.state.IBlockState;
|
2016-03-01 04:58:03 -08:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
2016-03-06 16:54:47 -08:00
|
|
|
import net.minecraft.util.math.MathHelper;
|
2014-11-25 19:56:35 -08:00
|
|
|
import net.minecraft.util.EnumFacing;
|
2013-05-23 01:01:19 -04:00
|
|
|
import net.minecraft.world.IBlockAccess;
|
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
|
|
2016-11-22 15:20:05 -08:00
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
|
|
2013-05-23 01:01:19 -04:00
|
|
|
/**
|
|
|
|
|
* This is a cellular-automata based finite fluid block implementation.
|
2014-11-25 19:56:35 -08:00
|
|
|
*
|
2013-05-23 01:01:19 -04:00
|
|
|
* It is highly recommended that you use/extend this class for finite fluid blocks.
|
2014-11-25 19:56:35 -08:00
|
|
|
*
|
2013-05-23 01:01:19 -04:00
|
|
|
*/
|
2013-07-16 21:40:49 -07:00
|
|
|
public class BlockFluidFinite extends BlockFluidBase
|
|
|
|
|
{
|
2014-01-29 18:34:23 -08:00
|
|
|
public BlockFluidFinite(Fluid fluid, Material material)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-01-29 18:34:23 -08:00
|
|
|
super(fluid, material);
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
2014-01-29 18:34:23 -08:00
|
|
|
|
2013-05-23 01:01:19 -04:00
|
|
|
@Override
|
2014-11-25 19:56:35 -08:00
|
|
|
public int getQuantaValue(IBlockAccess world, BlockPos pos)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
IBlockState state = world.getBlockState(pos);
|
2016-03-06 16:54:47 -08:00
|
|
|
if (state.getBlock().isAir(state, world, pos))
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
|
2014-11-25 19:56:35 -08:00
|
|
|
if (state.getBlock() != this)
|
2013-09-05 13:16:01 -04:00
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return -1;
|
|
|
|
|
}
|
2016-03-06 16:54:47 -08:00
|
|
|
return state.getValue(LEVEL) + 1;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2016-11-22 15:20:05 -08:00
|
|
|
public boolean canCollideCheck(@Nonnull IBlockState state, boolean fullHit)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2016-12-05 20:17:47 -08:00
|
|
|
return fullHit;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2013-07-16 21:40:49 -07:00
|
|
|
public int getMaxRenderHeightMeta()
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return quantaPerBlock - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2016-11-22 15:20:05 -08:00
|
|
|
public void updateTick(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Random rand)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
boolean changed = false;
|
2016-03-06 16:54:47 -08:00
|
|
|
int quantaRemaining = state.getValue(LEVEL) + 1;
|
2013-05-23 01:01:19 -04:00
|
|
|
|
|
|
|
|
// Flow vertically if possible
|
|
|
|
|
int prevRemaining = quantaRemaining;
|
2014-11-25 19:56:35 -08:00
|
|
|
quantaRemaining = tryToFlowVerticallyInto(world, pos, quantaRemaining);
|
2013-05-23 01:01:19 -04:00
|
|
|
|
2013-07-16 21:40:49 -07:00
|
|
|
if (quantaRemaining < 1)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return;
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else if (quantaRemaining != prevRemaining)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
changed = true;
|
2013-07-16 21:40:49 -07:00
|
|
|
if (quantaRemaining == 1)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2);
|
2013-05-23 01:01:19 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else if (quantaRemaining == 1)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Flow out if possible
|
2016-03-23 17:34:48 +03:00
|
|
|
int lowerThan = quantaRemaining - 1;
|
2013-05-23 01:01:19 -04:00
|
|
|
int total = quantaRemaining;
|
|
|
|
|
int count = 1;
|
|
|
|
|
|
2014-11-25 19:56:35 -08:00
|
|
|
for (EnumFacing side : EnumFacing.Plane.HORIZONTAL)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
BlockPos off = pos.offset(side);
|
|
|
|
|
if (displaceIfPossible(world, off))
|
|
|
|
|
world.setBlockToAir(off);
|
2013-07-16 21:40:49 -07:00
|
|
|
|
2016-03-23 17:34:48 +03:00
|
|
|
int quanta = getQuantaValueBelow(world, off, lowerThan);
|
2014-11-25 19:56:35 -08:00
|
|
|
if (quanta >= 0)
|
|
|
|
|
{
|
|
|
|
|
count++;
|
|
|
|
|
total += quanta;
|
|
|
|
|
}
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
|
|
|
|
|
if (count == 1)
|
|
|
|
|
{
|
|
|
|
|
if (changed)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(pos, state.withProperty(LEVEL, quantaRemaining - 1), 2);
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
|
2013-05-23 01:01:19 -04:00
|
|
|
int each = total / count;
|
|
|
|
|
int rem = total % count;
|
2013-07-16 21:40:49 -07:00
|
|
|
|
2014-11-25 19:56:35 -08:00
|
|
|
for (EnumFacing side : EnumFacing.Plane.HORIZONTAL)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
BlockPos off = pos.offset(side);
|
2016-03-23 17:34:48 +03:00
|
|
|
int quanta = getQuantaValueBelow(world, off, lowerThan);
|
2014-11-25 19:56:35 -08:00
|
|
|
if (quanta >= 0)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2016-03-23 17:34:48 +03:00
|
|
|
int newQuanta = each;
|
2014-11-25 19:56:35 -08:00
|
|
|
if (rem == count || rem > 1 && rand.nextInt(count - rem) != 0)
|
2013-09-05 13:16:01 -04:00
|
|
|
{
|
2016-03-23 17:34:48 +03:00
|
|
|
++newQuanta;
|
2014-11-25 19:56:35 -08:00
|
|
|
--rem;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-23 17:34:48 +03:00
|
|
|
if (newQuanta != quanta)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2016-03-23 17:34:48 +03:00
|
|
|
if (newQuanta == 0)
|
2014-11-25 19:56:35 -08:00
|
|
|
{
|
|
|
|
|
world.setBlockToAir(off);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-03-23 17:34:48 +03:00
|
|
|
world.setBlockState(off, getDefaultState().withProperty(LEVEL, newQuanta - 1), 2);
|
2014-11-25 19:56:35 -08:00
|
|
|
}
|
|
|
|
|
world.scheduleUpdate(off, this, tickRate);
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
2014-11-25 19:56:35 -08:00
|
|
|
--count;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
|
|
|
|
|
if (rem > 0)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
++each;
|
|
|
|
|
}
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(pos, state.withProperty(LEVEL, each - 1), 2);
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
|
2014-11-25 19:56:35 -08:00
|
|
|
public int tryToFlowVerticallyInto(World world, BlockPos pos, int amtToInput)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
IBlockState myState = world.getBlockState(pos);
|
|
|
|
|
BlockPos other = pos.add(0, densityDir, 0);
|
|
|
|
|
if (other.getY() < 0 || other.getY() >= world.getHeight())
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockToAir(pos);
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-25 19:56:35 -08:00
|
|
|
int amt = getQuantaValueBelow(world, other, quantaPerBlock);
|
2013-07-16 21:40:49 -07:00
|
|
|
if (amt >= 0)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
amt += amtToInput;
|
2013-07-16 21:40:49 -07:00
|
|
|
if (amt > quantaPerBlock)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(other, myState.withProperty(LEVEL, quantaPerBlock - 1), 3);
|
|
|
|
|
world.scheduleUpdate(other, this, tickRate);
|
2013-05-23 01:01:19 -04:00
|
|
|
return amt - quantaPerBlock;
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else if (amt > 0)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(other, myState.withProperty(LEVEL, amt - 1), 3);
|
|
|
|
|
world.scheduleUpdate(other, this, tickRate);
|
|
|
|
|
world.setBlockToAir(pos);
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return amtToInput;
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
int density_other = getDensity(world, other);
|
2013-07-16 21:40:49 -07:00
|
|
|
if (density_other == Integer.MAX_VALUE)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
if (displaceIfPossible(world, other))
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockState(other, myState.withProperty(LEVEL, amtToInput - 1), 3);
|
|
|
|
|
world.scheduleUpdate(other, this, tickRate);
|
|
|
|
|
world.setBlockToAir(pos);
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
return amtToInput;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
|
|
|
|
|
if (densityDir < 0)
|
|
|
|
|
{
|
2013-05-23 01:01:19 -04:00
|
|
|
if (density_other < density) // then swap
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
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));
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
|
|
|
|
}
|
2013-07-16 21:40:49 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (density_other > density)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
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));
|
2013-05-23 01:01:19 -04:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return amtToInput;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* IFluidBlock */
|
2016-12-05 20:17:47 -08:00
|
|
|
@Override
|
|
|
|
|
public int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace)
|
|
|
|
|
{
|
|
|
|
|
IBlockState existing = world.getBlockState(pos);
|
|
|
|
|
float quantaAmount = Fluid.BUCKET_VOLUME / quantaPerBlockFloat;
|
|
|
|
|
// If the stack contains more available fluid than the full source block,
|
|
|
|
|
// set a source block
|
|
|
|
|
int closest = Fluid.BUCKET_VOLUME;
|
|
|
|
|
int quanta = quantaPerBlock;
|
|
|
|
|
if (fluidStack.amount < closest)
|
|
|
|
|
{
|
|
|
|
|
// Figure out maximum level to match stack amount
|
2016-12-21 15:52:30 -08:00
|
|
|
closest = MathHelper.floor(quantaAmount * MathHelper.floor(fluidStack.amount / quantaAmount));
|
|
|
|
|
quanta = MathHelper.floor(closest / quantaAmount);
|
2016-12-05 20:17:47 -08:00
|
|
|
}
|
|
|
|
|
if (existing.getBlock() == this)
|
|
|
|
|
{
|
|
|
|
|
int existingQuanta = existing.getValue(LEVEL) + 1;
|
|
|
|
|
int missingQuanta = quantaPerBlock - existingQuanta;
|
2016-12-21 15:52:30 -08:00
|
|
|
closest = Math.min(closest, MathHelper.floor(missingQuanta * quantaAmount));
|
2016-12-05 20:17:47 -08:00
|
|
|
quanta = Math.min(quanta + existingQuanta, quantaPerBlock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If too little (or too much, technically impossible) fluid is to be placed, abort
|
|
|
|
|
if (quanta < 1 || quanta > 16)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (doPlace)
|
|
|
|
|
{
|
2017-05-01 17:25:45 -07:00
|
|
|
FluidUtil.destroyBlockOnFluidPlacement(world, pos);
|
2016-12-05 20:17:47 -08:00
|
|
|
world.setBlockState(pos, getDefaultState().withProperty(LEVEL, quanta - 1), 11);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return closest;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-23 01:01:19 -04:00
|
|
|
@Override
|
2014-11-25 19:56:35 -08:00
|
|
|
public FluidStack drain(World world, BlockPos pos, boolean doDrain)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2016-12-21 15:52:30 -08:00
|
|
|
final FluidStack fluidStack = new FluidStack(getFluid(), MathHelper.floor(getQuantaPercentage(world, pos) * Fluid.BUCKET_VOLUME));
|
2016-03-21 19:56:31 -07:00
|
|
|
|
2014-05-25 19:59:59 +02:00
|
|
|
if (doDrain)
|
|
|
|
|
{
|
2014-11-25 19:56:35 -08:00
|
|
|
world.setBlockToAir(pos);
|
2014-05-25 19:59:59 +02:00
|
|
|
}
|
2014-11-25 19:56:35 -08:00
|
|
|
|
2016-03-21 19:56:31 -07:00
|
|
|
return fluidStack;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2014-11-25 19:56:35 -08:00
|
|
|
public boolean canDrain(World world, BlockPos pos)
|
2013-07-16 21:40:49 -07:00
|
|
|
{
|
2014-05-25 19:59:59 +02:00
|
|
|
return true;
|
2013-05-23 01:01:19 -04:00
|
|
|
}
|
2016-03-06 16:54:47 -08:00
|
|
|
}
|