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
|
|
|
|
|
*/
|
|
|
|
|
|
2016-01-02 14:38:18 +01:00
|
|
|
package net.minecraftforge.fluids;
|
|
|
|
|
|
|
|
|
|
import net.minecraft.block.Block;
|
2016-06-18 16:29:28 -07:00
|
|
|
import net.minecraft.block.BlockDispenser;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraft.block.material.Material;
|
|
|
|
|
import net.minecraft.creativetab.CreativeTabs;
|
|
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
2016-06-03 18:26:41 -07:00
|
|
|
import net.minecraft.init.Items;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraft.item.Item;
|
|
|
|
|
import net.minecraft.item.ItemStack;
|
|
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
|
import net.minecraft.stats.StatList;
|
2016-05-16 22:20:31 +02:00
|
|
|
import net.minecraft.util.*;
|
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.RayTraceResult;
|
|
|
|
|
import net.minecraft.util.text.translation.I18n;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraft.world.World;
|
2016-06-03 18:26:41 -07:00
|
|
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraftforge.event.entity.player.FillBucketEvent;
|
2016-06-03 18:26:41 -07:00
|
|
|
import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraftforge.fml.common.eventhandler.Event;
|
|
|
|
|
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
|
|
|
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|
|
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
|
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
|
|
|
import net.minecraftforge.items.ItemHandlerHelper;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A universal bucket that can hold any liquid
|
|
|
|
|
*/
|
|
|
|
|
public class UniversalBucket extends Item implements IFluidContainerItem
|
|
|
|
|
{
|
|
|
|
|
|
2016-03-24 13:14:39 +03:00
|
|
|
private final int capacity; // how much the bucket holds
|
|
|
|
|
private final ItemStack empty; // empty item to return and recognize when filling
|
|
|
|
|
private final boolean nbtSensitive;
|
2016-01-02 14:38:18 +01:00
|
|
|
|
|
|
|
|
public UniversalBucket()
|
|
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
this(Fluid.BUCKET_VOLUME, new ItemStack(Items.BUCKET), false);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param capacity Capacity of the container
|
|
|
|
|
* @param empty Item used for filling with the bucket event and returned when emptied
|
|
|
|
|
* @param nbtSensitive Whether the empty item is NBT sensitive (usually true if empty and full are the same items)
|
|
|
|
|
*/
|
|
|
|
|
public UniversalBucket(int capacity, ItemStack empty, boolean nbtSensitive)
|
|
|
|
|
{
|
|
|
|
|
this.capacity = capacity;
|
|
|
|
|
this.empty = empty;
|
|
|
|
|
this.nbtSensitive = nbtSensitive;
|
|
|
|
|
|
|
|
|
|
this.setMaxStackSize(1);
|
|
|
|
|
|
2016-05-18 05:11:56 -07:00
|
|
|
this.setCreativeTab(CreativeTabs.MISC);
|
2016-06-18 16:29:28 -07:00
|
|
|
|
|
|
|
|
BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, DispenseFluidContainer.getInstance());
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
|
|
|
@Override
|
|
|
|
|
public void getSubItems(Item itemIn, CreativeTabs tab, List<ItemStack> subItems)
|
|
|
|
|
{
|
|
|
|
|
for (Fluid fluid : FluidRegistry.getRegisteredFluids().values())
|
|
|
|
|
{
|
|
|
|
|
// add all fluids that the bucket can be filled with
|
2016-03-24 13:14:39 +03:00
|
|
|
FluidStack fs = new FluidStack(fluid, getCapacity());
|
2016-01-02 14:38:18 +01:00
|
|
|
ItemStack stack = new ItemStack(this);
|
|
|
|
|
if (fill(stack, fs, true) == fs.amount)
|
|
|
|
|
{
|
|
|
|
|
subItems.add(stack);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getItemStackDisplayName(ItemStack stack)
|
|
|
|
|
{
|
|
|
|
|
FluidStack fluidStack = getFluid(stack);
|
|
|
|
|
if (fluidStack == null)
|
|
|
|
|
{
|
2016-03-24 13:14:39 +03:00
|
|
|
if(getEmpty() != null)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-03-24 13:14:39 +03:00
|
|
|
return getEmpty().getDisplayName();
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
return super.getItemStackDisplayName(stack);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String unloc = this.getUnlocalizedNameInefficiently(stack);
|
|
|
|
|
|
2016-03-06 16:54:47 -08:00
|
|
|
if (I18n.canTranslate(unloc + "." + fluidStack.getFluid().getName()))
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-03-06 16:54:47 -08:00
|
|
|
return I18n.translateToLocal(unloc + "." + fluidStack.getFluid().getName());
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-06 16:54:47 -08:00
|
|
|
return I18n.translateToLocalFormatted(unloc + ".name", fluidStack.getLocalizedName());
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2016-03-06 16:54:47 -08:00
|
|
|
public ActionResult<ItemStack> onItemRightClick(ItemStack itemstack, World world, EntityPlayer player, EnumHand hand)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
FluidStack fluidStack = getFluid(itemstack);
|
|
|
|
|
// empty bucket shouldn't exist, do nothing since it should be handled by the bucket event
|
|
|
|
|
if (fluidStack == null)
|
|
|
|
|
{
|
2016-03-06 16:54:47 -08:00
|
|
|
return ActionResult.newResult(EnumActionResult.PASS, itemstack);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clicked on a block?
|
2016-05-18 05:11:56 -07:00
|
|
|
RayTraceResult mop = this.rayTrace(world, player, false);
|
2016-05-16 22:20:31 +02:00
|
|
|
|
|
|
|
|
if(mop == null || mop.typeOfHit != RayTraceResult.Type.BLOCK)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-05-16 22:20:31 +02:00
|
|
|
return ActionResult.newResult(EnumActionResult.PASS, itemstack);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BlockPos clickPos = mop.getBlockPos();
|
|
|
|
|
// can we place liquid there?
|
|
|
|
|
if (world.isBlockModifiable(player, clickPos))
|
|
|
|
|
{
|
|
|
|
|
// the block adjacent to the side we clicked on
|
|
|
|
|
BlockPos targetPos = clickPos.offset(mop.sideHit);
|
2016-01-02 14:38:18 +01:00
|
|
|
|
2016-05-16 22:20:31 +02:00
|
|
|
// can the player place there?
|
|
|
|
|
if (player.canPlayerEdit(targetPos, mop.sideHit, itemstack))
|
|
|
|
|
{
|
|
|
|
|
// try placing liquid
|
2016-06-03 18:26:41 -07:00
|
|
|
if (FluidUtil.tryPlaceFluid(player, player.getEntityWorld(), fluidStack, targetPos)
|
2016-05-16 22:20:31 +02:00
|
|
|
&& !player.capabilities.isCreativeMode)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-05-16 22:20:31 +02:00
|
|
|
// success!
|
2016-05-18 05:11:56 -07:00
|
|
|
player.addStat(StatList.getObjectUseStats(this));
|
2016-05-16 22:20:31 +02:00
|
|
|
|
|
|
|
|
itemstack.stackSize--;
|
|
|
|
|
ItemStack emptyStack = getEmpty() != null ? getEmpty().copy() : new ItemStack(this);
|
|
|
|
|
|
|
|
|
|
// check whether we replace the item or add the empty one to the inventory
|
|
|
|
|
if (itemstack.stackSize <= 0)
|
|
|
|
|
{
|
|
|
|
|
return ActionResult.newResult(EnumActionResult.SUCCESS, emptyStack);
|
|
|
|
|
}
|
|
|
|
|
else
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-05-16 22:20:31 +02:00
|
|
|
// add empty bucket to player inventory
|
|
|
|
|
ItemHandlerHelper.giveItemToPlayer(player, emptyStack);
|
|
|
|
|
return ActionResult.newResult(EnumActionResult.SUCCESS, itemstack);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// couldn't place liquid there2
|
2016-03-06 16:54:47 -08:00
|
|
|
return ActionResult.newResult(EnumActionResult.FAIL, itemstack);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-05-16 22:20:31 +02:00
|
|
|
// compatibility
|
|
|
|
|
@Deprecated
|
2016-01-02 14:38:18 +01:00
|
|
|
public boolean tryPlaceFluid(Block block, World worldIn, BlockPos pos)
|
2016-05-16 22:20:31 +02:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
if (block instanceof IFluidBlock)
|
2016-05-16 22:20:31 +02:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
IFluidBlock fluidBlock = (IFluidBlock) block;
|
|
|
|
|
return FluidUtil.tryPlaceFluid(null, worldIn, new FluidStack(fluidBlock.getFluid(), Fluid.BUCKET_VOLUME), pos);
|
2016-05-16 22:20:31 +02:00
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
else if (block.getDefaultState().getMaterial() == Material.WATER)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
FluidUtil.tryPlaceFluid(null, worldIn, new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME), pos);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
else if (block.getDefaultState().getMaterial() == Material.LAVA)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
FluidUtil.tryPlaceFluid(null, worldIn, new FluidStack(FluidRegistry.LAVA, Fluid.BUCKET_VOLUME), pos);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
return false;
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SubscribeEvent(priority = EventPriority.LOW) // low priority so other mods can handle their stuff first
|
|
|
|
|
public void onFillBucket(FillBucketEvent event)
|
|
|
|
|
{
|
|
|
|
|
if (event.getResult() != Event.Result.DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
// event was already handled
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// not for us to handle
|
2016-06-03 18:26:41 -07:00
|
|
|
ItemStack emptyBucket = event.getEmptyBucket();
|
|
|
|
|
if (emptyBucket == null ||
|
|
|
|
|
!emptyBucket.isItemEqual(getEmpty()) ||
|
|
|
|
|
(isNbtSensitive() && ItemStack.areItemStackTagsEqual(emptyBucket, getEmpty())))
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// needs to target a block
|
2016-06-03 18:26:41 -07:00
|
|
|
RayTraceResult target = event.getTarget();
|
|
|
|
|
if (target == null || target.typeOfHit != RayTraceResult.Type.BLOCK)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 16:54:47 -08:00
|
|
|
World world = event.getWorld();
|
2016-06-03 18:26:41 -07:00
|
|
|
BlockPos pos = target.getBlockPos();
|
2016-01-02 14:38:18 +01:00
|
|
|
|
2016-06-03 18:26:41 -07:00
|
|
|
ItemStack singleBucket = emptyBucket.copy();
|
|
|
|
|
singleBucket.stackSize = 1;
|
2016-05-16 22:20:31 +02:00
|
|
|
|
2016-06-03 18:26:41 -07:00
|
|
|
ItemStack filledBucket = FluidUtil.tryPickUpFluid(singleBucket, event.getEntityPlayer(), world, pos, target.sideHit);
|
|
|
|
|
if (filledBucket != null)
|
|
|
|
|
{
|
|
|
|
|
event.setResult(Event.Result.ALLOW);
|
|
|
|
|
event.setFilledBucket(filledBucket);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// cancel event, otherwise the vanilla minecraft ItemBucket would
|
|
|
|
|
// convert it into a water/lava bucket depending on the blocks material
|
|
|
|
|
event.setCanceled(true);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static ItemStack getFilledBucket(UniversalBucket item, Fluid fluid)
|
|
|
|
|
{
|
|
|
|
|
ItemStack stack = new ItemStack(item);
|
2016-03-24 13:14:39 +03:00
|
|
|
item.fill(stack, new FluidStack(fluid, item.getCapacity()), true);
|
2016-01-02 14:38:18 +01:00
|
|
|
return stack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FluidContainer Management */
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public FluidStack getFluid(ItemStack container)
|
|
|
|
|
{
|
|
|
|
|
return FluidStack.loadFluidStackFromNBT(container.getTagCompound());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int getCapacity(ItemStack container)
|
|
|
|
|
{
|
2016-03-24 13:14:39 +03:00
|
|
|
return getCapacity();
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int fill(ItemStack container, FluidStack resource, boolean doFill)
|
|
|
|
|
{
|
|
|
|
|
// has to be exactly 1, must be handled from the caller
|
|
|
|
|
if (container.stackSize != 1)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// can only fill exact capacity
|
2016-06-03 18:26:41 -07:00
|
|
|
if (resource == null || resource.amount < getCapacity())
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
|
|
|
|
|
// already contains fluid?
|
|
|
|
|
if (getFluid(container) != null)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
|
|
|
|
|
// registered in the registry?
|
|
|
|
|
if (FluidRegistry.getBucketFluids().contains(resource.getFluid()))
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
// fill the container
|
|
|
|
|
if (doFill)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
NBTTagCompound tag = container.getTagCompound();
|
|
|
|
|
if (tag == null)
|
|
|
|
|
{
|
|
|
|
|
tag = new NBTTagCompound();
|
|
|
|
|
}
|
|
|
|
|
resource.writeToNBT(tag);
|
|
|
|
|
container.setTagCompound(tag);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
return getCapacity();
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
else if (resource.getFluid() == FluidRegistry.WATER)
|
|
|
|
|
{
|
|
|
|
|
if (doFill)
|
|
|
|
|
{
|
2016-06-13 20:01:28 -07:00
|
|
|
container.deserializeNBT(new ItemStack(Items.WATER_BUCKET).serializeNBT());
|
2016-06-03 18:26:41 -07:00
|
|
|
}
|
|
|
|
|
return getCapacity();
|
|
|
|
|
}
|
|
|
|
|
else if (resource.getFluid() == FluidRegistry.LAVA)
|
|
|
|
|
{
|
|
|
|
|
if (doFill)
|
|
|
|
|
{
|
2016-06-13 20:01:28 -07:00
|
|
|
container.deserializeNBT(new ItemStack(Items.LAVA_BUCKET).serializeNBT());
|
2016-06-03 18:26:41 -07:00
|
|
|
}
|
|
|
|
|
return getCapacity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public FluidStack drain(ItemStack container, int maxDrain, boolean doDrain)
|
|
|
|
|
{
|
2016-06-03 18:26:41 -07:00
|
|
|
// has to be exactly 1, must be handled from the caller
|
|
|
|
|
if (container.stackSize != 1)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-02 14:38:18 +01:00
|
|
|
// can only drain everything at once
|
2016-06-03 18:26:41 -07:00
|
|
|
if (maxDrain < getCapacity(container))
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FluidStack fluidStack = getFluid(container);
|
|
|
|
|
if (doDrain && fluidStack != null)
|
|
|
|
|
{
|
2016-03-24 13:14:39 +03:00
|
|
|
if(getEmpty() != null)
|
2016-01-02 14:38:18 +01:00
|
|
|
{
|
2016-06-13 20:01:28 -07:00
|
|
|
container.deserializeNBT(getEmpty().serializeNBT());
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
container.stackSize = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fluidStack;
|
|
|
|
|
}
|
2016-03-24 13:14:39 +03:00
|
|
|
|
|
|
|
|
public int getCapacity()
|
|
|
|
|
{
|
|
|
|
|
return capacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ItemStack getEmpty()
|
|
|
|
|
{
|
|
|
|
|
return empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isNbtSensitive()
|
|
|
|
|
{
|
|
|
|
|
return nbtSensitive;
|
|
|
|
|
}
|
2016-06-03 18:26:41 -07:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt)
|
|
|
|
|
{
|
|
|
|
|
return new FluidBucketWrapper(stack);
|
|
|
|
|
}
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|