[1.11.x] Refine fluid placement utilities (#3509)

This commit is contained in:
mezz 2016-12-05 20:17:47 -08:00 committed by LexManos
parent 160427b12c
commit 8eea766288
12 changed files with 615 additions and 69 deletions

View file

@ -358,6 +358,20 @@ public class BlockFluidClassic extends BlockFluidBase
}
/* IFluidBlock */
@Override
public int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace)
{
if (fluidStack.amount < Fluid.BUCKET_VOLUME)
{
return 0;
}
if (doPlace)
{
world.setBlockState(pos, this.getDefaultState(), 11);
}
return Fluid.BUCKET_VOLUME;
}
@Override
public FluidStack drain(World world, BlockPos pos, boolean doDrain)
{

View file

@ -64,7 +64,7 @@ public class BlockFluidFinite extends BlockFluidBase
@Override
public boolean canCollideCheck(@Nonnull IBlockState state, boolean fullHit)
{
return fullHit && state.getValue(LEVEL) == quantaPerBlock - 1;
return fullHit;
}
@Override
@ -244,6 +244,41 @@ public class BlockFluidFinite extends BlockFluidBase
}
/* IFluidBlock */
@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
closest = MathHelper.floor_float(quantaAmount * MathHelper.floor_float(fluidStack.amount / quantaAmount));
quanta = MathHelper.floor_float(closest / quantaAmount);
}
if (existing.getBlock() == this)
{
int existingQuanta = existing.getValue(LEVEL) + 1;
int missingQuanta = quantaPerBlock - existingQuanta;
closest = Math.min(closest, MathHelper.floor_float(missingQuanta * quantaAmount));
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)
{
world.setBlockState(pos, getDefaultState().withProperty(LEVEL, quanta - 1), 11);
}
return closest;
}
@Override
public FluidStack drain(World world, BlockPos pos, boolean doDrain)
{

View file

@ -109,13 +109,13 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem
FluidStack fluidStack = fluidHandler.drain(Fluid.BUCKET_VOLUME, false);
EnumFacing dispenserFacing = source.getBlockState().getValue(BlockDispenser.FACING);
BlockPos blockpos = source.getBlockPos().offset(dispenserFacing);
FluidActionResult result = fluidStack != null ? FluidUtil.tryPlaceFluid(null, source.getWorld(), blockpos, stack, fluidStack) : FluidActionResult.FAILURE;
if (fluidStack != null && fluidStack.amount == Fluid.BUCKET_VOLUME && FluidUtil.tryPlaceFluid(null, source.getWorld(), fluidStack, blockpos))
if (result.isSuccess())
{
fluidHandler.drain(Fluid.BUCKET_VOLUME, true);
ItemStack drainedStack = fluidHandler.getContainer();
ItemStack drainedStack = result.getResult();
if (stack.func_190916_E() == 1)
if (drainedStack.func_190916_E() == 1)
{
return drainedStack;
}
@ -124,7 +124,7 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem
this.dispenseBehavior.dispense(source, drainedStack);
}
ItemStack stackCopy = stack.copy();
ItemStack stackCopy = drainedStack.copy();
stackCopy.func_190918_g(1);
return stackCopy;
}

View file

@ -37,7 +37,9 @@ import net.minecraft.world.World;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fluids.capability.templates.VoidFluidHandler;
import net.minecraftforge.fluids.capability.wrappers.BlockLiquidWrapper;
import net.minecraftforge.fluids.capability.wrappers.BlockWrapper;
import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
@ -419,62 +421,6 @@ public class FluidUtil
return null;
}
/**
* Tries to place a fluid in the world in block form.
* Makes a fluid emptying sound when successful.
* Checks if water-like fluids should vaporize like in the nether.
*
* Modeled after {@link net.minecraft.item.ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)}
*
* @param player Player who places the fluid. May be null for blocks like dispensers.
* @param worldIn World to place the fluid in
* @param fluidStack The fluidStack to place.
* @param pos The position in the world to place the fluid block
* @return true if successful
*/
public static boolean tryPlaceFluid(@Nullable EntityPlayer player, World worldIn, FluidStack fluidStack, BlockPos pos)
{
if (worldIn == null || fluidStack == null || pos == null)
{
return false;
}
Fluid fluid = fluidStack.getFluid();
if (fluid == null || !fluid.canBePlacedInWorld())
{
return false;
}
// check that we can place the fluid at the destination
IBlockState destBlockState = worldIn.getBlockState(pos);
Material destMaterial = destBlockState.getMaterial();
boolean isDestNonSolid = !destMaterial.isSolid();
boolean isDestReplaceable = destBlockState.getBlock().isReplaceable(worldIn, pos);
if (!worldIn.isAirBlock(pos) && !isDestNonSolid && !isDestReplaceable)
{
return false; // Non-air, solid, unreplacable block. We can't put fluid here.
}
if (worldIn.provider.doesWaterVaporize() && fluid.doesVaporize(fluidStack))
{
fluid.vaporize(player, worldIn, pos, fluidStack);
}
else
{
if (!worldIn.isRemote && (isDestNonSolid || isDestReplaceable) && !destMaterial.isLiquid())
{
worldIn.destroyBlock(pos, true);
}
SoundEvent soundevent = fluid.getEmptySound(fluidStack);
worldIn.playSound(player, pos, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
IBlockState fluidBlockState = fluid.getBlock().getDefaultState();
worldIn.setBlockState(pos, fluidBlockState, 11);
}
return true;
}
/**
* Attempts to pick up a fluid in the world and put it in an empty container item.
*
@ -511,4 +457,82 @@ public class FluidUtil
}
return FluidActionResult.FAILURE;
}
/**
* Tries to place a fluid in the world in block form and drains the container.
* Makes a fluid emptying 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 net.minecraft.item.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 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)
{
if (world == null || resource == null || pos == null)
{
return FluidActionResult.FAILURE;
}
Fluid fluid = resource.getFluid();
if (fluid == null || !fluid.canBePlacedInWorld())
{
return FluidActionResult.FAILURE;
}
// check that we can place the fluid at the destination
IBlockState destBlockState = world.getBlockState(pos);
Material destMaterial = destBlockState.getMaterial();
boolean isDestNonSolid = !destMaterial.isSolid();
boolean isDestReplaceable = destBlockState.getBlock().isReplaceable(world, pos);
if (!world.isAirBlock(pos) && !isDestNonSolid && !isDestReplaceable)
{
return FluidActionResult.FAILURE; // Non-air, solid, unreplacable block. We can't put fluid here.
}
if (world.provider.doesWaterVaporize() && fluid.doesVaporize(resource))
{
fluid.vaporize(player, world, pos, resource);
return tryEmptyContainer(container, new VoidFluidHandler(), Integer.MAX_VALUE, player, true);
}
else
{
if (!world.isRemote && (isDestNonSolid || isDestReplaceable) && !destMaterial.isLiquid())
{
world.destroyBlock(pos, true);
}
// Defer the placement to the fluid block
// Instead of actually "filling", the fluid handler method replaces the block
Block block = fluid.getBlock();
IFluidHandler handler;
if (block instanceof IFluidBlock)
{
handler = new FluidBlockWrapper((IFluidBlock) block, world, pos);
}
else if (block instanceof BlockLiquid)
{
handler = new BlockLiquidWrapper((BlockLiquid) block, world, pos);
}
else
{
handler = new BlockWrapper(block, world, pos);
}
FluidActionResult result = tryEmptyContainer(container, handler, Integer.MAX_VALUE, player, true);
if (result.isSuccess())
{
SoundEvent soundevent = fluid.getEmptySound(resource);
world.playSound(player, pos, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
}
return result;
}
}
}

View file

@ -22,6 +22,8 @@ package net.minecraftforge.fluids;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* Implement this interface on Block classes which represent world-placeable Fluids.
*
@ -35,6 +37,20 @@ public interface IFluidBlock
*/
Fluid getFluid();
/**
* Attempts to place the block at a given position. The placed block's level will correspond
* to the provided fluid amount.
* This method should be called by fluid containers such as buckets, but it is recommended
* to use {@link FluidUtil}.
*
* @param world the world to place the block in
* @param pos the position to place the block at
* @param fluidStack the fluid stack to get the required data from
* @param doPlace if false, the placement will only be simulated
* @return the amount of fluid extracted from the provided stack to achieve some fluid level
*/
int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace);
/**
* Attempt to drain the block. This method should be called by devices such as pumps.
*

View file

@ -177,14 +177,15 @@ public class UniversalBucket extends Item
if (player.canPlayerEdit(targetPos, mop.sideHit, itemstack))
{
// try placing liquid
if (FluidUtil.tryPlaceFluid(player, player.getEntityWorld(), fluidStack, targetPos)
&& !player.capabilities.isCreativeMode)
FluidActionResult result = FluidUtil.tryPlaceFluid(player, world, targetPos, itemstack, fluidStack);
if (result.isSuccess() && !player.capabilities.isCreativeMode)
{
// success!
player.addStat(StatList.getObjectUseStats(this));
itemstack.func_190918_g(1);
ItemStack emptyStack = !getEmpty().func_190926_b() ? getEmpty().copy() : new ItemStack(this);
ItemStack drained = result.getResult();
ItemStack emptyStack = !drained.func_190926_b() ? drained.copy() : new ItemStack(this);
// check whether we replace the item or add the empty one to the inventory
if (itemstack.func_190926_b())

View file

@ -0,0 +1,91 @@
/*
* 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
*/
package net.minecraftforge.fluids.capability.templates;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import javax.annotation.Nullable;
import static net.minecraftforge.fluids.capability.templates.EmptyFluidHandler.EMPTY_TANK_INFO;
import static net.minecraftforge.fluids.capability.templates.EmptyFluidHandler.EMPTY_TANK_PROPERTIES_ARRAY;
/**
* VoidFluidHandler is a template fluid handler that can be filled indefinitely without ever getting full.
* It does not store fluid that gets filled into it, but "destroys" it upon receiving it.
*/
public class VoidFluidHandler implements IFluidHandler, IFluidTank
{
public static final EmptyFluidHandler INSTANCE = new EmptyFluidHandler();
public VoidFluidHandler() {}
@Override
public IFluidTankProperties[] getTankProperties()
{
return EMPTY_TANK_PROPERTIES_ARRAY;
}
@Override
@Nullable
public FluidStack getFluid()
{
return null;
}
@Override
public int getFluidAmount()
{
return 0;
}
@Override
public int getCapacity()
{
return Integer.MAX_VALUE;
}
@Override
public FluidTankInfo getInfo()
{
return EMPTY_TANK_INFO;
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
return resource.amount;
}
@Override
public FluidStack drain(FluidStack resource, boolean doDrain)
{
return null;
}
@Override
public FluidStack drain(int maxDrain, boolean doDrain)
{
return null;
}
}

View file

@ -26,7 +26,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemBucket;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@ -39,7 +39,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
/**
* Wrapper to handle vanilla Water or Lava as an IFluidHandler.
* Methods are modeled after {@link net.minecraft.item.ItemBucket#onItemRightClick(ItemStack, World, EntityPlayer, EnumHand)}
* Methods are modeled after {@link ItemBucket#onItemRightClick(World, EntityPlayer, EnumHand)}
*/
public class BlockLiquidWrapper implements IFluidHandler
{
@ -69,7 +69,20 @@ public class BlockLiquidWrapper implements IFluidHandler
@Override
public int fill(FluidStack resource, boolean doFill)
{
return 0;
// NOTE: "Filling" means placement in this context!
if (resource.amount < Fluid.BUCKET_VOLUME)
{
return 0;
}
if (doFill)
{
Material material = blockLiquid.getDefaultState().getMaterial();
BlockLiquid block = BlockLiquid.getStaticBlock(material);
world.setBlockState(blockPos, block.getDefaultState().withProperty(BlockLiquid.LEVEL, 0), 11);
}
return Fluid.BUCKET_VOLUME;
}
@Nullable

View file

@ -0,0 +1,61 @@
/*
* 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
*/
package net.minecraftforge.fluids.capability.wrappers;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.templates.VoidFluidHandler;
/**
* Wrapper around any block, only accounts for fluid placement, otherwise the block acts a void.
* If the block in question inherits from the default Vanilla or Forge implementations,
* consider using {@link BlockLiquidWrapper} or {@link FluidBlockWrapper} respectively.
*/
public class BlockWrapper extends VoidFluidHandler
{
protected final Block block;
protected final World world;
protected final BlockPos blockPos;
public BlockWrapper(Block block, World world, BlockPos blockPos)
{
this.block = block;
this.world = world;
this.blockPos = blockPos;
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
// NOTE: "Filling" means placement in this context!
if (resource.amount < Fluid.BUCKET_VOLUME)
{
return 0;
}
if (doFill)
{
world.setBlockState(blockPos, block.getDefaultState(), 11);
}
return Fluid.BUCKET_VOLUME;
}
}

View file

@ -62,7 +62,12 @@ public class FluidBlockWrapper implements IFluidHandler
@Override
public int fill(FluidStack resource, boolean doFill)
{
return 0;
// NOTE: "Filling" means placement in this context!
if (resource == null)
{
return 0;
}
return fluidBlock.place(world, blockPos, resource, doFill);
}
@Nullable

View file

@ -0,0 +1,270 @@
package net.minecraftforge.debug;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.ItemMeshDefinition;
import net.minecraft.client.renderer.block.model.ModelBakery;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.block.statemap.StateMapperBase;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.*;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.*;
import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack;
import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import static net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack.FLUID_NBT_KEY;
@Mod(modid = FluidPlacementTest.MODID, name = "ForgeDebugFluidPlacement", version = FluidPlacementTest.VERSION)
public class FluidPlacementTest
{
public static final String MODID = "forgedebugfluidplacement";
public static final String VERSION = "1.0";
public static final boolean ENABLE = true;
@SidedProxy
public static CommonProxy proxy;
@EventHandler
public void preInit(FMLPreInitializationEvent event)
{
if (ENABLE && ModelFluidDebug.ENABLE)
{
proxy.preInit(event);
}
}
public static class CommonProxy
{
public void preInit(FMLPreInitializationEvent event)
{
FluidRegistry.registerFluid(FiniteFluid.instance);
FluidRegistry.addBucketForFluid(FiniteFluid.instance);
GameRegistry.register(EmptyFluidContainer.instance);
GameRegistry.register(FluidContainer.instance);
GameRegistry.register(FiniteFluidBlock.instance);
GameRegistry.register(new ItemBlock(FiniteFluidBlock.instance).setRegistryName(FiniteFluidBlock.instance.getRegistryName()));
MinecraftForge.EVENT_BUS.register(FluidContainer.instance);
}
}
public static class ServerProxy extends CommonProxy
{
}
public static class ClientProxy extends CommonProxy
{
private static ModelResourceLocation fluidLocation = new ModelResourceLocation(MODID.toLowerCase() + ":" + FiniteFluidBlock.name, "normal");
@Override
public void preInit(FMLPreInitializationEvent event)
{
super.preInit(event);
Item fluid = Item.getItemFromBlock(FiniteFluidBlock.instance);
ModelLoader.setCustomModelResourceLocation(EmptyFluidContainer.instance, 0, new ModelResourceLocation("forge:bucket", "inventory"));
ModelLoader.setBucketModelDefinition(FluidContainer.instance);
// no need to pass the locations here, since they'll be loaded by the block model logic.
ModelBakery.registerItemVariants(fluid);
ModelLoader.setCustomMeshDefinition(fluid, new ItemMeshDefinition()
{
public ModelResourceLocation getModelLocation(ItemStack stack)
{
return fluidLocation;
}
});
ModelLoader.setCustomStateMapper(FiniteFluidBlock.instance, new StateMapperBase()
{
protected ModelResourceLocation getModelResourceLocation(IBlockState state)
{
return fluidLocation;
}
});
}
}
public static final class FiniteFluid extends Fluid
{
public static final String name = "finitefluid";
public static final FiniteFluid instance = new FiniteFluid();
private FiniteFluid()
{
super(name, new ResourceLocation("blocks/water_still"), new ResourceLocation("blocks/water_flow"));
}
@Override
public int getColor()
{
return 0xFFFFFF00;
}
@Override
public String getLocalizedName(FluidStack stack)
{
return "Finite Fluid";
}
}
public static final class FiniteFluidBlock extends BlockFluidFinite
{
public static final FiniteFluidBlock instance = new FiniteFluidBlock();
public static final String name = "finite_fluid_block";
private FiniteFluidBlock()
{
super(FiniteFluid.instance, Material.WATER);
setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
setUnlocalizedName(MODID + ":" + name);
setRegistryName(MODID, name);
}
}
public static final class EmptyFluidContainer extends ItemBucket
{
public static final EmptyFluidContainer instance = new EmptyFluidContainer();
public static final String name = "empty_fluid_container";
private EmptyFluidContainer()
{
super(Blocks.AIR);
setRegistryName(MODID, name);
setUnlocalizedName(MODID + ":" + name);
setMaxStackSize(16);
}
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable NBTTagCompound nbt)
{
return new EmptyContainerHandler(stack);
}
private static final class EmptyContainerHandler extends FluidBucketWrapper
{
public EmptyContainerHandler(@Nonnull ItemStack container)
{
super(container);
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
if (container.func_190916_E() != 1 || resource == null || resource.amount > Fluid.BUCKET_VOLUME || container
.getItem() instanceof ItemBucketMilk || getFluid() != null || !canFillFluidType(resource))
{
return 0;
}
if (doFill)
{
container = new ItemStack(FluidContainer.instance);
NBTTagCompound tag = new NBTTagCompound();
NBTTagCompound fluidTag = new NBTTagCompound();
resource.writeToNBT(fluidTag);
tag.setTag(FLUID_NBT_KEY, fluidTag);
container.setTagCompound(tag);
}
return resource.amount;
}
}
}
public static final class FluidContainer extends UniversalBucket
{
public static final FluidContainer instance = new FluidContainer();
public static final String name = "fluid_container";
private FluidContainer()
{
super(1000, new ItemStack(EmptyFluidContainer.instance), false);
setCreativeTab(CreativeTabs.MISC);
setRegistryName(MODID, name);
setUnlocalizedName(MODID + ":" + name);
}
@Nonnull
@Override
public String getItemStackDisplayName(@Nonnull ItemStack stack)
{
FluidStack fluid = getFluid(stack);
if (fluid == null || fluid.getFluid() == null)
{
return "Empty Variable Container";
}
return "Variable Container (" + getFluid(stack).getLocalizedName() + ")";
}
@Override
public FluidStack getFluid(ItemStack container)
{
container = container.copy();
if (container.getTagCompound() != null)
container.setTagCompound(container.getTagCompound().getCompoundTag(FLUID_NBT_KEY));
return super.getFluid(container);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, EntityPlayer playerIn, List<String> tooltip, boolean advanced)
{
FluidStack fluid = getFluid(stack);
if (fluid != null)
{
tooltip.add(fluid.amount + "/1000");
}
}
@Override
public void getSubItems(@Nonnull Item itemIn, @Nonnull CreativeTabs tab, @Nonnull NonNullList<ItemStack> subItems)
{
Fluid[] fluids = new Fluid[]{FluidRegistry.WATER, FluidRegistry.LAVA, FiniteFluid.instance, ModelFluidDebug.TestFluid.instance};
// add 16 variable fillings
for (Fluid fluid : fluids)
{
for (int amount = 125; amount <= 1000; amount += 125)
{
for (int offset = 63; offset >= 0; offset -= 63)
{
FluidStack fs = new FluidStack(fluid, amount - offset);
ItemStack stack = new ItemStack(this);
NBTTagCompound tag = stack.getTagCompound();
if (tag == null)
{
tag = new NBTTagCompound();
}
NBTTagCompound fluidTag = new NBTTagCompound();
fs.writeToNBT(fluidTag);
tag.setTag(FLUID_NBT_KEY, fluidTag);
stack.setTagCompound(tag);
subItems.add(stack);
}
}
}
}
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt)
{
return new FluidHandlerItemStack.SwapEmpty(stack, new ItemStack(EmptyFluidContainer.instance), 1000);
}
}
}

View file

@ -0,0 +1,16 @@
{
"forge_marker": 1,
"defaults": {
"model": "forge:fluid",
"transform": "forge:default-item"
},
"variants": {
"normal": [
{
"custom": {
"fluid": "finitefluid"
}
}
]
}
}