[1.11.x] Refine fluid placement utilities (#3509)
This commit is contained in:
parent
160427b12c
commit
8eea766288
12 changed files with 615 additions and 69 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
270
src/test/java/net/minecraftforge/debug/FluidPlacementTest.java
Normal file
270
src/test/java/net/minecraftforge/debug/FluidPlacementTest.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"forge_marker": 1,
|
||||
"defaults": {
|
||||
"model": "forge:fluid",
|
||||
"transform": "forge:default-item"
|
||||
},
|
||||
"variants": {
|
||||
"normal": [
|
||||
{
|
||||
"custom": {
|
||||
"fluid": "finitefluid"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue