2016-06-23 03:49:47 +00:00
|
|
|
/*
|
|
|
|
* Minecraft Forge
|
2018-07-01 21:17:28 +00:00
|
|
|
* Copyright (c) 2016-2018.
|
2016-06-23 03:49:47 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2016-01-02 13:38:18 +00:00
|
|
|
package net.minecraftforge.fluids;
|
|
|
|
|
2016-11-13 22:09:54 +00:00
|
|
|
import javax.annotation.Nonnull;
|
2016-06-04 01:26:41 +00:00
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
2017-05-02 00:25:45 +00:00
|
|
|
import com.google.common.base.Preconditions;
|
2016-05-16 20:20:31 +00:00
|
|
|
import net.minecraft.block.Block;
|
|
|
|
import net.minecraft.block.material.Material;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraft.block.state.IBlockState;
|
2016-01-02 13:38:18 +00:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
2018-09-21 06:50:50 +00:00
|
|
|
import net.minecraft.item.BlockItemUseContext;
|
2017-05-02 00:25:45 +00:00
|
|
|
import net.minecraft.item.ItemBucket;
|
2017-03-11 05:06:40 +00:00
|
|
|
import net.minecraft.init.Items;
|
2016-01-02 13:38:18 +00:00
|
|
|
import net.minecraft.item.ItemStack;
|
2017-03-11 05:06:40 +00:00
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraft.tileentity.TileEntity;
|
2016-01-02 13:38:18 +00:00
|
|
|
import net.minecraft.util.EnumFacing;
|
2017-05-02 00:25:45 +00:00
|
|
|
import net.minecraft.util.EnumHand;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraft.util.SoundCategory;
|
2016-05-16 20:20:31 +00:00
|
|
|
import net.minecraft.util.SoundEvent;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.world.World;
|
2018-06-21 19:37:32 +00:00
|
|
|
import net.minecraftforge.common.ForgeMod;
|
2018-09-09 21:27:15 +00:00
|
|
|
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
|
|
|
import net.minecraftforge.fluids.capability.IFluidHandler;
|
2016-10-10 07:44:50 +00:00
|
|
|
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
|
2016-12-06 04:17:47 +00:00
|
|
|
import net.minecraftforge.fluids.capability.wrappers.BlockWrapper;
|
2016-06-04 01:26:41 +00:00
|
|
|
import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper;
|
2017-05-02 00:25:45 +00:00
|
|
|
import net.minecraftforge.items.CapabilityItemHandler;
|
2016-01-02 13:38:18 +00:00
|
|
|
import net.minecraftforge.items.IItemHandler;
|
|
|
|
import net.minecraftforge.items.ItemHandlerHelper;
|
|
|
|
|
|
|
|
public class FluidUtil
|
|
|
|
{
|
|
|
|
private FluidUtil()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-05-02 00:25:45 +00:00
|
|
|
/**
|
|
|
|
* Used to handle the common case of a player holding a fluid item and right-clicking on a fluid handler block.
|
|
|
|
* First it tries to fill the item from the block,
|
|
|
|
* if that action fails then it tries to drain the item into the block.
|
|
|
|
* Automatically updates the item in the player's hand and stashes any extra items created.
|
|
|
|
*
|
|
|
|
* @param player The player doing the interaction between the item and fluid handler block.
|
|
|
|
* @param hand The player's hand that is holding an item that should interact with the fluid handler block.
|
|
|
|
* @param world The world that contains the fluid handler block.
|
|
|
|
* @param pos The position of the fluid handler block in the world.
|
|
|
|
* @param side The side of the block to interact with. May be null.
|
|
|
|
* @return true if the interaction succeeded and updated the item held by the player, false otherwise.
|
|
|
|
*/
|
|
|
|
public static boolean interactWithFluidHandler(@Nonnull EntityPlayer player, @Nonnull EnumHand hand, @Nonnull World world, @Nonnull BlockPos pos, @Nullable EnumFacing side)
|
|
|
|
{
|
|
|
|
Preconditions.checkNotNull(world);
|
|
|
|
Preconditions.checkNotNull(pos);
|
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
return getFluidHandler(world, pos, side).map(handler -> interactWithFluidHandler(player, hand, handler)).orElse(false);
|
2017-06-26 01:22:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to handle the common case of a player holding a fluid item and right-clicking on a fluid handler.
|
|
|
|
* First it tries to fill the item from the handler,
|
|
|
|
* if that action fails then it tries to drain the item into the handler.
|
|
|
|
* Automatically updates the item in the player's hand and stashes any extra items created.
|
|
|
|
*
|
|
|
|
* @param player The player doing the interaction between the item and fluid handler.
|
|
|
|
* @param hand The player's hand that is holding an item that should interact with the fluid handler.
|
|
|
|
* @param handler The fluid handler.
|
|
|
|
* @return true if the interaction succeeded and updated the item held by the player, false otherwise.
|
|
|
|
*/
|
|
|
|
public static boolean interactWithFluidHandler(@Nonnull EntityPlayer player, @Nonnull EnumHand hand, @Nonnull IFluidHandler handler)
|
|
|
|
{
|
|
|
|
Preconditions.checkNotNull(player);
|
|
|
|
Preconditions.checkNotNull(hand);
|
|
|
|
Preconditions.checkNotNull(handler);
|
|
|
|
|
2017-05-02 00:25:45 +00:00
|
|
|
ItemStack heldItem = player.getHeldItem(hand);
|
|
|
|
if (!heldItem.isEmpty())
|
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
return player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
|
|
|
.map(playerInventory -> {
|
2018-09-21 06:50:50 +00:00
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
FluidActionResult fluidActionResult = tryFillContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
|
|
|
if (!fluidActionResult.isSuccess())
|
|
|
|
{
|
|
|
|
fluidActionResult = tryEmptyContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
|
|
|
}
|
2018-09-21 06:50:50 +00:00
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
if (fluidActionResult.isSuccess())
|
|
|
|
{
|
|
|
|
player.setHeldItem(hand, fluidActionResult.getResult());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
})
|
|
|
|
.orElse(false);
|
2017-05-02 00:25:45 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-04 01:26:41 +00:00
|
|
|
/**
|
|
|
|
* Fill a container from the given fluidSource.
|
|
|
|
*
|
|
|
|
* @param container The container to be filled. Will not be modified.
|
2016-10-10 07:44:50 +00:00
|
|
|
* Separate handling must be done to reduce the stack size, stow containers, etc, on success.
|
2018-01-18 21:23:30 +00:00
|
|
|
* See {@link #tryFillContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}.
|
2016-06-04 01:26:41 +00:00
|
|
|
* @param fluidSource The fluid handler to be drained.
|
|
|
|
* @param maxAmount The largest amount of fluid that should be transferred.
|
|
|
|
* @param player The player to make the filling noise. Pass null for no noise.
|
|
|
|
* @param doFill true if the container should actually be filled, false if it should be simulated.
|
2016-10-10 07:44:50 +00:00
|
|
|
* @return a {@link FluidActionResult} holding the filled container if successful.
|
2016-06-04 01:26:41 +00:00
|
|
|
*/
|
2016-11-13 22:09:54 +00:00
|
|
|
@Nonnull
|
2016-10-10 07:44:50 +00:00
|
|
|
public static FluidActionResult tryFillContainer(@Nonnull ItemStack container, IFluidHandler fluidSource, int maxAmount, @Nullable EntityPlayer player, boolean doFill)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
2018-09-09 21:27:15 +00:00
|
|
|
return getFluidHandler(containerCopy)
|
|
|
|
.map(containerFluidHandler -> {
|
|
|
|
FluidStack simulatedTransfer = tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, false);
|
|
|
|
if (simulatedTransfer != null)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
if (doFill)
|
|
|
|
{
|
|
|
|
tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, true);
|
|
|
|
if (player != null)
|
|
|
|
{
|
|
|
|
SoundEvent soundevent = simulatedTransfer.getFluid().getFillSound(simulatedTransfer);
|
|
|
|
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
containerFluidHandler.fill(simulatedTransfer, true);
|
|
|
|
}
|
2018-09-21 06:50:50 +00:00
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
|
|
|
return new FluidActionResult(resultContainer);
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
|
|
|
})
|
|
|
|
.orElse(FluidActionResult.FAILURE);
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes a filled container and tries to empty it into the given tank.
|
|
|
|
*
|
|
|
|
* @param container The filled container. Will not be modified.
|
2016-10-10 07:44:50 +00:00
|
|
|
* Separate handling must be done to reduce the stack size, stow containers, etc, on success.
|
2018-01-18 21:23:30 +00:00
|
|
|
* See {@link #tryEmptyContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}.
|
2016-06-04 01:26:41 +00:00
|
|
|
* @param fluidDestination The fluid handler to be filled by the container.
|
|
|
|
* @param maxAmount The largest amount of fluid that should be transferred.
|
|
|
|
* @param player Player for making the bucket drained sound. Pass null for no noise.
|
|
|
|
* @param doDrain true if the container should actually be drained, false if it should be simulated.
|
2016-10-10 07:44:50 +00:00
|
|
|
* @return a {@link FluidActionResult} holding the empty container if the fluid handler was filled.
|
|
|
|
* NOTE If the container is consumable, the empty container will be null on success.
|
2016-06-04 01:26:41 +00:00
|
|
|
*/
|
2016-11-13 22:09:54 +00:00
|
|
|
@Nonnull
|
2016-10-10 07:44:50 +00:00
|
|
|
public static FluidActionResult tryEmptyContainer(@Nonnull ItemStack container, IFluidHandler fluidDestination, int maxAmount, @Nullable EntityPlayer player, boolean doDrain)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
2018-09-09 21:27:15 +00:00
|
|
|
return getFluidHandler(containerCopy)
|
|
|
|
.map(containerFluidHandler -> {
|
|
|
|
if (doDrain)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
FluidStack transfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, true);
|
|
|
|
if (transfer != null)
|
|
|
|
{
|
|
|
|
if (player != null)
|
|
|
|
{
|
|
|
|
SoundEvent soundevent = transfer.getFluid().getEmptySound(transfer);
|
|
|
|
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
|
|
|
}
|
|
|
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
|
|
|
return new FluidActionResult(resultContainer);
|
|
|
|
}
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FluidStack simulatedTransfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, false);
|
|
|
|
if (simulatedTransfer != null)
|
|
|
|
{
|
|
|
|
containerFluidHandler.drain(simulatedTransfer, true);
|
|
|
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
|
|
|
return new FluidActionResult(resultContainer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FluidActionResult.FAILURE;
|
|
|
|
})
|
|
|
|
.orElse(FluidActionResult.FAILURE);
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes an Fluid Container Item and tries to fill it from the given tank.
|
|
|
|
* If the player is in creative mode, the container will not be modified on success, and no additional items created.
|
|
|
|
* If the input itemstack has a stacksize > 1 it will stow the filled container in the given inventory.
|
|
|
|
* If the inventory does not accept it, it will be given to the player or dropped at the players feet.
|
|
|
|
* If player is null in this case, the action will be aborted.
|
|
|
|
*
|
2016-10-10 07:44:50 +00:00
|
|
|
* @param container The Fluid Container ItemStack to fill.
|
|
|
|
* Will not be modified directly, if modifications are necessary a modified copy is returned in the result.
|
2016-06-04 01:26:41 +00:00
|
|
|
* @param fluidSource The fluid source to fill from
|
|
|
|
* @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put
|
|
|
|
* @param maxAmount Maximum amount of fluid to take from the tank.
|
2016-10-10 07:44:50 +00:00
|
|
|
* @param player The player that gets the items the inventory can't take.
|
|
|
|
* Can be null, only used if the inventory cannot take the filled stack.
|
|
|
|
* @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure.
|
2018-01-18 21:23:30 +00:00
|
|
|
* @deprecated use {@link #tryFillContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}
|
2016-06-04 01:26:41 +00:00
|
|
|
*/
|
2018-01-18 21:23:30 +00:00
|
|
|
@Deprecated // TODO remove in 1.13
|
2016-10-10 07:44:50 +00:00
|
|
|
@Nonnull
|
|
|
|
public static FluidActionResult tryFillContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidSource, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player)
|
2018-01-18 21:23:30 +00:00
|
|
|
{
|
|
|
|
return tryFillContainerAndStow(container, fluidSource, inventory, maxAmount, player, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes an Fluid Container Item and tries to fill it from the given tank.
|
|
|
|
* If the player is in creative mode, the container will not be modified on success, and no additional items created.
|
|
|
|
* If the input itemstack has a stacksize > 1 it will stow the filled container in the given inventory.
|
|
|
|
* If the inventory does not accept it, it will be given to the player or dropped at the players feet.
|
|
|
|
* If player is null in this case, the action will be aborted.
|
|
|
|
*
|
|
|
|
* @param container The Fluid Container ItemStack to fill.
|
|
|
|
* Will not be modified directly, if modifications are necessary a modified copy is returned in the result.
|
|
|
|
* @param fluidSource The fluid source to fill from
|
|
|
|
* @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put
|
|
|
|
* @param maxAmount Maximum amount of fluid to take from the tank.
|
|
|
|
* @param player The player that gets the items the inventory can't take.
|
|
|
|
* Can be null, only used if the inventory cannot take the filled stack.
|
|
|
|
* @param doFill true if the container should actually be filled, false if it should be simulated.
|
|
|
|
* @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure.
|
|
|
|
*/
|
|
|
|
@Nonnull
|
|
|
|
public static FluidActionResult tryFillContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidSource, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player, boolean doFill)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-12-21 23:52:30 +00:00
|
|
|
if (container.isEmpty())
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (player != null && player.capabilities.isCreativeMode)
|
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, doFill);
|
2016-10-10 07:44:50 +00:00
|
|
|
if (filledReal.isSuccess())
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return new FluidActionResult(container); // creative mode: item does not change
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
}
|
2016-12-21 23:52:30 +00:00
|
|
|
else if (container.getCount() == 1) // don't need to stow anything, just fill the container stack
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, doFill);
|
2016-10-10 07:44:50 +00:00
|
|
|
if (filledReal.isSuccess())
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return filledReal;
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
FluidActionResult filledSimulated = tryFillContainer(container, fluidSource, maxAmount, player, false);
|
|
|
|
if (filledSimulated.isSuccess())
|
2016-01-02 13:38:18 +00:00
|
|
|
{
|
2016-06-04 01:26:41 +00:00
|
|
|
// check if we can give the itemStack to the inventory
|
2016-10-10 07:44:50 +00:00
|
|
|
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, filledSimulated.getResult(), true);
|
2016-12-21 23:52:30 +00:00
|
|
|
if (remainder.isEmpty() || player != null)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, doFill);
|
|
|
|
remainder = ItemHandlerHelper.insertItemStacked(inventory, filledReal.getResult(), !doFill);
|
2016-06-04 01:26:41 +00:00
|
|
|
|
|
|
|
// give it to the player or drop it at their feet
|
2018-01-18 21:23:30 +00:00
|
|
|
if (!remainder.isEmpty() && player != null && doFill)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
|
|
|
ItemHandlerHelper.giveItemToPlayer(player, remainder);
|
|
|
|
}
|
|
|
|
|
2016-10-10 07:44:50 +00:00
|
|
|
ItemStack containerCopy = container.copy();
|
2016-12-21 23:52:30 +00:00
|
|
|
containerCopy.shrink(1);
|
2016-10-10 07:44:50 +00:00
|
|
|
return new FluidActionResult(containerCopy);
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-10 07:44:50 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes an Fluid Container Item, tries to empty it into the fluid handler, and stows it in the given inventory.
|
|
|
|
* If the player is in creative mode, the container will not be modified on success, and no additional items created.
|
|
|
|
* If the input itemstack has a stacksize > 1 it will stow the emptied container in the given inventory.
|
|
|
|
* If the inventory does not accept the emptied container, it will be given to the player or dropped at the players feet.
|
|
|
|
* If player is null in this case, the action will be aborted.
|
|
|
|
*
|
2016-10-10 07:44:50 +00:00
|
|
|
* @param container The filled Fluid Container Itemstack to empty.
|
|
|
|
* Will not be modified directly, if modifications are necessary a modified copy is returned in the result.
|
2016-06-23 02:20:50 +00:00
|
|
|
* @param fluidDestination The fluid destination to fill from the fluid container.
|
|
|
|
* @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put
|
|
|
|
* @param maxAmount Maximum amount of fluid to take from the tank.
|
|
|
|
* @param player The player that gets the items the inventory can't take. Can be null, only used if the inventory cannot take the filled stack.
|
2016-10-10 07:44:50 +00:00
|
|
|
* @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure.
|
2018-01-18 21:23:30 +00:00
|
|
|
* @deprecated use {@link #tryEmptyContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}
|
2016-06-04 01:26:41 +00:00
|
|
|
*/
|
2018-01-18 21:23:30 +00:00
|
|
|
@Deprecated // TODO: remove in 1.13
|
2016-10-10 07:44:50 +00:00
|
|
|
@Nonnull
|
|
|
|
public static FluidActionResult tryEmptyContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidDestination, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player)
|
2018-01-18 21:23:30 +00:00
|
|
|
{
|
|
|
|
return tryEmptyContainerAndStow(container, fluidDestination, inventory, maxAmount, player, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes an Fluid Container Item, tries to empty it into the fluid handler, and stows it in the given inventory.
|
|
|
|
* If the player is in creative mode, the container will not be modified on success, and no additional items created.
|
|
|
|
* If the input itemstack has a stacksize > 1 it will stow the emptied container in the given inventory.
|
|
|
|
* If the inventory does not accept the emptied container, it will be given to the player or dropped at the players feet.
|
|
|
|
* If player is null in this case, the action will be aborted.
|
|
|
|
*
|
|
|
|
* @param container The filled Fluid Container Itemstack to empty.
|
|
|
|
* Will not be modified directly, if modifications are necessary a modified copy is returned in the result.
|
|
|
|
* @param fluidDestination The fluid destination to fill from the fluid container.
|
|
|
|
* @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put
|
|
|
|
* @param maxAmount Maximum amount of fluid to take from the tank.
|
|
|
|
* @param player The player that gets the items the inventory can't take. Can be null, only used if the inventory cannot take the filled stack.
|
|
|
|
* @param doDrain true if the container should actually be drained, false if it should be simulated.
|
|
|
|
* @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure.
|
|
|
|
*/
|
|
|
|
@Nonnull
|
|
|
|
public static FluidActionResult tryEmptyContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidDestination, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player, boolean doDrain)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-12-21 23:52:30 +00:00
|
|
|
if (container.isEmpty())
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
2016-01-02 13:38:18 +00:00
|
|
|
|
2016-06-04 01:26:41 +00:00
|
|
|
if (player != null && player.capabilities.isCreativeMode)
|
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, doDrain);
|
2016-10-10 07:44:50 +00:00
|
|
|
if (emptiedReal.isSuccess())
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return new FluidActionResult(container); // creative mode: item does not change
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
}
|
2016-12-21 23:52:30 +00:00
|
|
|
else if (container.getCount() == 1) // don't need to stow anything, just fill and edit the container stack
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, doDrain);
|
2016-10-10 07:44:50 +00:00
|
|
|
if (emptiedReal.isSuccess())
|
2016-11-13 22:09:54 +00:00
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
return emptiedReal;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-10 07:44:50 +00:00
|
|
|
FluidActionResult emptiedSimulated = tryEmptyContainer(container, fluidDestination, maxAmount, player, false);
|
|
|
|
if (emptiedSimulated.isSuccess())
|
2016-11-13 22:09:54 +00:00
|
|
|
{
|
|
|
|
// check if we can give the itemStack to the inventory
|
2016-10-10 07:44:50 +00:00
|
|
|
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedSimulated.getResult(), true);
|
2016-12-21 23:52:30 +00:00
|
|
|
if (remainder.isEmpty() || player != null)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-01-18 21:23:30 +00:00
|
|
|
FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, doDrain);
|
|
|
|
remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedReal.getResult(), !doDrain);
|
2016-06-04 01:26:41 +00:00
|
|
|
|
2016-11-13 22:09:54 +00:00
|
|
|
// give it to the player or drop it at their feet
|
2018-01-18 21:23:30 +00:00
|
|
|
if (!remainder.isEmpty() && player != null && doDrain)
|
2016-11-13 22:09:54 +00:00
|
|
|
{
|
|
|
|
ItemHandlerHelper.giveItemToPlayer(player, remainder);
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
2016-11-13 22:09:54 +00:00
|
|
|
|
2016-10-10 07:44:50 +00:00
|
|
|
ItemStack containerCopy = container.copy();
|
2016-12-21 23:52:30 +00:00
|
|
|
containerCopy.shrink(1);
|
2016-10-10 07:44:50 +00:00
|
|
|
return new FluidActionResult(containerCopy);
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-10 07:44:50 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
|
|
|
|
2016-06-04 01:26:41 +00:00
|
|
|
/**
|
2017-05-02 00:25:45 +00:00
|
|
|
* Fill a destination fluid handler from a source fluid handler with a max amount.
|
|
|
|
* To specify a fluid to transfer instead of max amount, use {@link #tryFluidTransfer(IFluidHandler, IFluidHandler, FluidStack, boolean)}
|
|
|
|
* To transfer as much as possible, use {@link Integer#MAX_VALUE} for maxAmount.
|
2016-06-04 01:26:41 +00:00
|
|
|
*
|
|
|
|
* @param fluidDestination The fluid handler to be filled.
|
|
|
|
* @param fluidSource The fluid handler to be drained.
|
|
|
|
* @param maxAmount The largest amount of fluid that should be transferred.
|
|
|
|
* @param doTransfer True if the transfer should actually be done, false if it should be simulated.
|
|
|
|
* @return the fluidStack that was transferred from the source to the destination. null on failure.
|
|
|
|
*/
|
|
|
|
@Nullable
|
|
|
|
public static FluidStack tryFluidTransfer(IFluidHandler fluidDestination, IFluidHandler fluidSource, int maxAmount, boolean doTransfer)
|
2016-05-16 20:20:31 +00:00
|
|
|
{
|
2016-06-04 01:26:41 +00:00
|
|
|
FluidStack drainable = fluidSource.drain(maxAmount, false);
|
|
|
|
if (drainable != null && drainable.amount > 0)
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
return tryFluidTransfer_Internal(fluidDestination, fluidSource, drainable, doTransfer);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill a destination fluid handler from a source fluid handler using a specific fluid.
|
|
|
|
* To specify a max amount to transfer instead of specific fluid, use {@link #tryFluidTransfer(IFluidHandler, IFluidHandler, int, boolean)}
|
|
|
|
* To transfer as much as possible, use {@link Integer#MAX_VALUE} for resource.amount.
|
|
|
|
*
|
|
|
|
* @param fluidDestination The fluid handler to be filled.
|
|
|
|
* @param fluidSource The fluid handler to be drained.
|
|
|
|
* @param resource The fluid that should be transferred. Amount represents the maximum amount to transfer.
|
|
|
|
* @param doTransfer True if the transfer should actually be done, false if it should be simulated.
|
|
|
|
* @return the fluidStack that was transferred from the source to the destination. null on failure.
|
|
|
|
*/
|
|
|
|
@Nullable
|
|
|
|
public static FluidStack tryFluidTransfer(IFluidHandler fluidDestination, IFluidHandler fluidSource, FluidStack resource, boolean doTransfer)
|
|
|
|
{
|
|
|
|
FluidStack drainable = fluidSource.drain(resource, false);
|
|
|
|
if (drainable != null && drainable.amount > 0 && resource.isFluidEqual(drainable))
|
|
|
|
{
|
|
|
|
return tryFluidTransfer_Internal(fluidDestination, fluidSource, drainable, doTransfer);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal method for filling a destination fluid handler from a source fluid handler using a specific fluid.
|
|
|
|
* Assumes that "drainable" can be drained from "fluidSource".
|
|
|
|
*
|
|
|
|
* Modders: Instead of this method, use {@link #tryFluidTransfer(IFluidHandler, IFluidHandler, FluidStack, boolean)}
|
|
|
|
* or {@link #tryFluidTransfer(IFluidHandler, IFluidHandler, int, boolean)}.
|
|
|
|
*/
|
|
|
|
@Nullable
|
|
|
|
private static FluidStack tryFluidTransfer_Internal(IFluidHandler fluidDestination, IFluidHandler fluidSource, FluidStack drainable, boolean doTransfer)
|
|
|
|
{
|
|
|
|
int fillableAmount = fluidDestination.fill(drainable, false);
|
|
|
|
if (fillableAmount > 0)
|
|
|
|
{
|
|
|
|
if (doTransfer)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
FluidStack drained = fluidSource.drain(fillableAmount, true);
|
|
|
|
if (drained != null)
|
2016-10-10 07:44:50 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
drained.amount = fluidDestination.fill(drained, true);
|
|
|
|
return drained;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-02 00:25:45 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
drainable.amount = fillableAmount;
|
|
|
|
return drainable;
|
|
|
|
}
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
return null;
|
2016-05-16 20:20:31 +00:00
|
|
|
}
|
|
|
|
|
2016-01-02 13:38:18 +00:00
|
|
|
/**
|
2016-10-10 07:44:50 +00:00
|
|
|
* Helper method to get an {@link IFluidHandlerItem} for an itemStack.
|
2016-01-02 13:38:18 +00:00
|
|
|
*
|
2016-10-10 07:44:50 +00:00
|
|
|
* The itemStack passed in here WILL be modified, the {@link IFluidHandlerItem} acts on it directly.
|
|
|
|
* Some {@link IFluidHandlerItem} will change the item entirely, always use {@link IFluidHandlerItem#getContainer()}
|
|
|
|
* after using the fluid handler to get the resulting item back.
|
2016-06-04 01:26:41 +00:00
|
|
|
*
|
|
|
|
* Note that the itemStack MUST have a stackSize of 1 if you want to fill or drain it.
|
2016-10-10 07:44:50 +00:00
|
|
|
* You can't fill or drain multiple items at once, if you do then liquid is multiplied or destroyed.
|
2016-06-04 01:26:41 +00:00
|
|
|
*
|
|
|
|
* Vanilla buckets will be converted to universal buckets if they are enabled.
|
2016-01-02 13:38:18 +00:00
|
|
|
*/
|
2018-09-09 21:27:15 +00:00
|
|
|
public static OptionalCapabilityInstance<IFluidHandlerItem> getFluidHandler(@Nonnull ItemStack itemStack)
|
2016-01-02 13:38:18 +00:00
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to get the fluid contained in an itemStack
|
|
|
|
*/
|
2018-09-09 21:27:15 +00:00
|
|
|
public static OptionalCapabilityInstance<FluidStack> getFluidContained(@Nonnull ItemStack container)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-12-21 23:52:30 +00:00
|
|
|
if (!container.isEmpty())
|
2016-01-02 13:38:18 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
container = ItemHandlerHelper.copyStackWithSize(container, 1);
|
2018-09-09 21:27:15 +00:00
|
|
|
return getFluidHandler(container)
|
|
|
|
.map(handler -> handler.drain(Integer.MAX_VALUE, false));
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
return OptionalCapabilityInstance.empty();
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
|
|
|
|
2016-06-04 01:26:41 +00:00
|
|
|
/**
|
|
|
|
* Helper method to get an IFluidHandler for at a block position.
|
|
|
|
*/
|
2018-09-09 21:27:15 +00:00
|
|
|
public static OptionalCapabilityInstance<IFluidHandler> getFluidHandler(World world, BlockPos blockPos, @Nullable EnumFacing side)
|
2016-05-16 20:20:31 +00:00
|
|
|
{
|
2016-06-04 01:26:41 +00:00
|
|
|
IBlockState state = world.getBlockState(blockPos);
|
|
|
|
Block block = state.getBlock();
|
|
|
|
|
|
|
|
if (block.hasTileEntity(state))
|
|
|
|
{
|
|
|
|
TileEntity tileEntity = world.getTileEntity(blockPos);
|
2018-09-09 21:27:15 +00:00
|
|
|
if (tileEntity != null)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
|
|
|
return tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side);
|
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
}/* TODO fluids blocks?
|
2018-04-13 00:17:39 +00:00
|
|
|
if (block instanceof IFluidBlock)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
return OptionalCapabilityInstance.of(() -> new FluidBlockWrapper((IFluidBlock) block, world, blockPos));
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
else if (block instanceof BlockLiquid)
|
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
return OptionalCapabilityInstance.of(() -> new BlockLiquidWrapper((BlockLiquid) block, world, blockPos));
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
*/
|
|
|
|
return OptionalCapabilityInstance.empty();
|
2016-05-16 20:20:31 +00:00
|
|
|
}
|
|
|
|
|
2016-06-04 01:26:41 +00:00
|
|
|
/**
|
|
|
|
* Attempts to pick up a fluid in the world and put it in an empty container item.
|
|
|
|
*
|
2016-10-10 07:44:50 +00:00
|
|
|
* @param emptyContainer The empty container to fill.
|
|
|
|
* Will not be modified directly, if modifications are necessary a modified copy is returned in the result.
|
2016-06-04 01:26:41 +00:00
|
|
|
* @param playerIn The player filling the container. Optional.
|
|
|
|
* @param worldIn The world the fluid is in.
|
|
|
|
* @param pos The position of the fluid in the world.
|
|
|
|
* @param side The side of the fluid that is being drained.
|
2016-10-10 07:44:50 +00:00
|
|
|
* @return a {@link FluidActionResult} holding the result and the resulting container.
|
2016-06-04 01:26:41 +00:00
|
|
|
*/
|
2016-11-13 22:09:54 +00:00
|
|
|
@Nonnull
|
2016-10-10 07:44:50 +00:00
|
|
|
public static FluidActionResult tryPickUpFluid(@Nonnull ItemStack emptyContainer, @Nullable EntityPlayer playerIn, World worldIn, BlockPos pos, EnumFacing side)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2016-12-21 23:52:30 +00:00
|
|
|
if (emptyContainer.isEmpty() || worldIn == null || pos == null)
|
2016-10-10 07:44:50 +00:00
|
|
|
{
|
|
|
|
return FluidActionResult.FAILURE;
|
2016-06-04 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
2016-08-12 08:36:18 +00:00
|
|
|
IBlockState state = worldIn.getBlockState(pos);
|
|
|
|
Block block = state.getBlock();
|
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
/* TODO fluid blocks?
|
2016-08-12 08:36:18 +00:00
|
|
|
if (block instanceof IFluidBlock || block instanceof BlockLiquid)
|
2016-06-04 01:26:41 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
IFluidHandler targetFluidHandler = getFluidHandler(worldIn, pos, side);
|
2016-08-12 08:36:18 +00:00
|
|
|
if (targetFluidHandler != null)
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
return tryFillContainer(emptyContainer, targetFluidHandler, Integer.MAX_VALUE, playerIn, true);
|
2016-08-12 08:36:18 +00:00
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
}*/
|
2016-10-10 07:44:50 +00:00
|
|
|
return FluidActionResult.FAILURE;
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|
2016-12-06 04:17:47 +00:00
|
|
|
|
|
|
|
/**
|
2017-05-02 00:25:45 +00:00
|
|
|
* ItemStack version of {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, IFluidHandler, FluidStack)}.
|
|
|
|
* Use the returned {@link FluidActionResult} to update the container ItemStack.
|
2016-12-06 04:17:47 +00:00
|
|
|
*
|
|
|
|
* @param player Player who places the fluid. May be null for blocks like dispensers.
|
|
|
|
* @param world World to place the fluid in
|
|
|
|
* @param pos The position in the world to place the fluid block
|
|
|
|
* @param container The fluid container holding the fluidStack to place
|
|
|
|
* @param resource The fluidStack to place
|
|
|
|
* @return the container's ItemStack with the remaining amount of fluid if the placement was successful, null otherwise
|
|
|
|
*/
|
|
|
|
@Nonnull
|
|
|
|
public static FluidActionResult tryPlaceFluid(@Nullable EntityPlayer player, World world, BlockPos pos, @Nonnull ItemStack container, FluidStack resource)
|
2017-05-02 00:25:45 +00:00
|
|
|
{
|
|
|
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
2018-09-09 21:27:15 +00:00
|
|
|
return getFluidHandler(containerCopy)
|
|
|
|
.filter(handler -> tryPlaceFluid(player, world, pos, handler, resource))
|
|
|
|
.map(IFluidHandlerItem::getContainer)
|
|
|
|
.map(FluidActionResult::new)
|
|
|
|
.orElse(FluidActionResult.FAILURE);
|
2017-05-02 00:25:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to place a fluid resource into the world as a block and drains the fluidSource.
|
|
|
|
* Makes a fluid emptying or vaporization sound when successful.
|
|
|
|
* Honors the amount of fluid contained by the used container.
|
|
|
|
* Checks if water-like fluids should vaporize like in the nether.
|
|
|
|
*
|
|
|
|
* Modeled after {@link ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)}
|
|
|
|
*
|
|
|
|
* @param player Player who places the fluid. May be null for blocks like dispensers.
|
|
|
|
* @param world World to place the fluid in
|
|
|
|
* @param pos The position in the world to place the fluid block
|
|
|
|
* @param fluidSource The fluid source holding the fluidStack to place
|
|
|
|
* @param resource The fluidStack to place.
|
|
|
|
* @return true if the placement was successful, false otherwise
|
|
|
|
*/
|
|
|
|
public static boolean tryPlaceFluid(@Nullable EntityPlayer player, World world, BlockPos pos, IFluidHandler fluidSource, FluidStack resource)
|
2016-12-06 04:17:47 +00:00
|
|
|
{
|
|
|
|
if (world == null || resource == null || pos == null)
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
return false;
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Fluid fluid = resource.getFluid();
|
|
|
|
if (fluid == null || !fluid.canBePlacedInWorld())
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fluidSource.drain(resource, false) == null)
|
|
|
|
{
|
|
|
|
return false;
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 06:50:50 +00:00
|
|
|
BlockItemUseContext context = new BlockItemUseContext(world, player, ItemStack.EMPTY, pos, EnumFacing.UP, 0, 0, 0); //TODO: This neds proper context...
|
|
|
|
|
2016-12-06 04:17:47 +00:00
|
|
|
// check that we can place the fluid at the destination
|
|
|
|
IBlockState destBlockState = world.getBlockState(pos);
|
|
|
|
Material destMaterial = destBlockState.getMaterial();
|
|
|
|
boolean isDestNonSolid = !destMaterial.isSolid();
|
2018-09-21 06:50:50 +00:00
|
|
|
boolean isDestReplaceable = destBlockState.func_196953_a(context);
|
2016-12-06 04:17:47 +00:00
|
|
|
if (!world.isAirBlock(pos) && !isDestNonSolid && !isDestReplaceable)
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
return false; // Non-air, solid, unreplacable block. We can't put fluid here.
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (world.provider.doesWaterVaporize() && fluid.doesVaporize(resource))
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
FluidStack result = fluidSource.drain(resource, true);
|
|
|
|
if (result != null)
|
|
|
|
{
|
|
|
|
result.getFluid().vaporize(player, world, pos, result);
|
|
|
|
return true;
|
|
|
|
}
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
// This fluid handler places the fluid block when filled
|
|
|
|
IFluidHandler handler = getFluidBlockHandler(fluid, world, pos);
|
|
|
|
FluidStack result = tryFluidTransfer(handler, fluidSource, resource, true);
|
|
|
|
if (result != null)
|
2016-12-06 04:17:47 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
SoundEvent soundevent = resource.getFluid().getEmptySound(resource);
|
|
|
|
world.playSound(player, pos, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
|
|
|
return true;
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
2017-05-02 00:25:45 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2016-12-06 04:17:47 +00:00
|
|
|
|
2017-05-02 00:25:45 +00:00
|
|
|
/**
|
|
|
|
* Internal method for getting a fluid block handler for placing a fluid.
|
|
|
|
*
|
|
|
|
* Modders: Instead of this method, use {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, ItemStack, FluidStack)}
|
|
|
|
* or {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, IFluidHandler, FluidStack)}
|
|
|
|
*/
|
|
|
|
private static IFluidHandler getFluidBlockHandler(Fluid fluid, World world, BlockPos pos)
|
|
|
|
{
|
2018-09-09 21:27:15 +00:00
|
|
|
Block block = fluid.getBlock();/* TODO fluid blocks?
|
2017-05-02 00:25:45 +00:00
|
|
|
if (block instanceof IFluidBlock)
|
|
|
|
{
|
|
|
|
return new FluidBlockWrapper((IFluidBlock) block, world, pos);
|
|
|
|
}
|
|
|
|
else if (block instanceof BlockLiquid)
|
|
|
|
{
|
|
|
|
return new BlockLiquidWrapper((BlockLiquid) block, world, pos);
|
|
|
|
}
|
2018-09-09 21:27:15 +00:00
|
|
|
else*/
|
2017-05-02 00:25:45 +00:00
|
|
|
{
|
|
|
|
return new BlockWrapper(block, world, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroys a block when a fluid is placed in the same position.
|
|
|
|
* Modeled after {@link ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)}
|
|
|
|
*
|
|
|
|
* This is a helper method for implementing {@link IFluidBlock#place(World, BlockPos, FluidStack, boolean)}.
|
|
|
|
*
|
|
|
|
* @param world the world that the fluid will be placed in
|
|
|
|
* @param pos the location that the fluid will be placed
|
|
|
|
*/
|
|
|
|
public static void destroyBlockOnFluidPlacement(World world, BlockPos pos)
|
|
|
|
{
|
|
|
|
if (!world.isRemote)
|
|
|
|
{
|
|
|
|
IBlockState destBlockState = world.getBlockState(pos);
|
|
|
|
Material destMaterial = destBlockState.getMaterial();
|
|
|
|
boolean isDestNonSolid = !destMaterial.isSolid();
|
2018-09-21 06:50:50 +00:00
|
|
|
boolean isDestReplaceable = false; //TODO: Needs BlockItemUseContext destBlockState.getBlock().isReplaceable(world, pos);
|
2017-05-02 00:25:45 +00:00
|
|
|
if ((isDestNonSolid || isDestReplaceable) && !destMaterial.isLiquid())
|
2016-12-06 04:17:47 +00:00
|
|
|
{
|
2017-05-02 00:25:45 +00:00
|
|
|
world.destroyBlock(pos, true);
|
2016-12-06 04:17:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-11 05:06:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param fluidStack contents used to fill the bucket.
|
|
|
|
* FluidStack is used instead of Fluid to preserve fluid NBT, the amount is ignored.
|
|
|
|
* @return a filled vanilla bucket or filled universal bucket.
|
|
|
|
* Returns empty itemStack if none of the enabled buckets can hold the fluid.
|
|
|
|
*/
|
|
|
|
@Nonnull
|
|
|
|
public static ItemStack getFilledBucket(@Nonnull FluidStack fluidStack)
|
2018-09-18 04:04:02 +00:00
|
|
|
{/* TODO fluids
|
2017-03-11 05:06:40 +00:00
|
|
|
Fluid fluid = fluidStack.getFluid();
|
|
|
|
|
2018-09-09 21:27:15 +00:00
|
|
|
if (fluidStack.tag == null || fluidStack.tag.isEmpty())
|
2017-03-11 05:06:40 +00:00
|
|
|
{
|
|
|
|
if (fluid == FluidRegistry.WATER)
|
|
|
|
{
|
|
|
|
return new ItemStack(Items.WATER_BUCKET);
|
|
|
|
}
|
|
|
|
else if (fluid == FluidRegistry.LAVA)
|
|
|
|
{
|
|
|
|
return new ItemStack(Items.LAVA_BUCKET);
|
|
|
|
}
|
|
|
|
else if (fluid.getName().equals("milk"))
|
|
|
|
{
|
|
|
|
return new ItemStack(Items.MILK_BUCKET);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FluidRegistry.isUniversalBucketEnabled() && FluidRegistry.getBucketFluids().contains(fluid))
|
|
|
|
{
|
2018-06-21 19:37:32 +00:00
|
|
|
UniversalBucket bucket = ForgeMod.getInstance().universalBucket;
|
2017-03-11 05:06:40 +00:00
|
|
|
ItemStack filledBucket = new ItemStack(bucket);
|
|
|
|
FluidStack fluidContents = new FluidStack(fluidStack, bucket.getCapacity());
|
|
|
|
|
|
|
|
NBTTagCompound tag = new NBTTagCompound();
|
|
|
|
fluidContents.writeToNBT(tag);
|
|
|
|
filledBucket.setTagCompound(tag);
|
|
|
|
|
|
|
|
return filledBucket;
|
|
|
|
}
|
2018-09-18 04:04:02 +00:00
|
|
|
*/
|
2017-03-11 05:06:40 +00:00
|
|
|
return ItemStack.EMPTY;
|
|
|
|
}
|
2016-01-02 13:38:18 +00:00
|
|
|
}
|