Created
October 5, 2017 05:47
-
-
Save jabelar/73e47e4bf57e977b04c0c94048730f72 to your computer and use it in GitHub Desktop.
onRightClick() example for a Minecraft Forge 1.12.x item fluid handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Override | |
@Nonnull | |
public ActionResult<ItemStack> onItemRightClick(@Nonnull World parWorld, @Nonnull EntityPlayer parPlayer, @Nonnull EnumHand parHand) | |
{ | |
// DEBUG | |
System.out.println("onItemRightClick for ItemSlimeBag for hand = "+parHand); | |
ItemStack itemStack = parPlayer.getHeldItem(parHand); | |
// clicked on a block? | |
RayTraceResult mop = rayTrace(parWorld, parPlayer, true); | |
if(mop == null || mop.typeOfHit != RayTraceResult.Type.BLOCK) | |
{ | |
return ActionResult.newResult(EnumActionResult.PASS, itemStack); | |
} | |
// DEBUG | |
System.out.println("Slime bag used"); | |
BlockPos clickPos = mop.getBlockPos(); | |
FluidStack fluidStack = getFluidStack(itemStack); | |
// can we place block there? | |
if (parWorld.isBlockModifiable(parPlayer, clickPos)) | |
{ | |
// the block adjacent to the side we clicked on | |
BlockPos targetPos = clickPos.offset(mop.sideHit); | |
// can the player place there? | |
if (parPlayer.canPlayerEdit(targetPos, mop.sideHit, itemStack)) | |
{ | |
if (fluidStack == null || fluidStack.amount <= 0) | |
{ | |
// DEBUG | |
System.out.println("Fluid stack in item is empty so try to fill"); | |
return tryFillAlt(parWorld, parPlayer, mop, itemStack); | |
} | |
else | |
{ | |
// DEBUG | |
System.out.println("Fluid stack is not empty so try to place"); | |
return tryPlaceAlt(parWorld, parPlayer, targetPos, itemStack); | |
} | |
} | |
else // player cannot edit | |
{ | |
// DEBUG | |
System.out.println("Failed to place fluid because player cannot edit"); | |
// couldn't place liquid there | |
return ActionResult.newResult(EnumActionResult.FAIL, itemStack); | |
} | |
} | |
else // cannot place blocks at that location | |
{ | |
// DEBUG | |
System.out.println("Failed to place fluid because location not modifiable"); | |
// couldn't place liquid there | |
return ActionResult.newResult(EnumActionResult.FAIL, itemStack); | |
} | |
} | |
/** | |
* Try place alt. | |
* | |
* @param parWorld the par world | |
* @param parPlayer the par player | |
* @param parPos the par pos | |
* @param parStack the par stack | |
* @return the action result | |
*/ | |
public ActionResult<ItemStack> tryPlaceAlt(World parWorld, EntityPlayer parPlayer, BlockPos parPos, ItemStack parStack) | |
{ | |
ActionResult<ItemStack> resultPass = new ActionResult<ItemStack>(EnumActionResult.PASS, parStack); | |
ActionResult<ItemStack> resultFail = new ActionResult<ItemStack>(EnumActionResult.FAIL, parStack); | |
if (parWorld == null || parPos == null) // not valid location to attempt to place | |
{ | |
// DEBUG | |
System.out.println("not valid location to place at"); | |
return resultFail; | |
} | |
else // valid location to attempt to place | |
{ | |
// DEBUG | |
System.out.println("Valid location to place at"); | |
IFluidHandlerItem containerFluidHandler = FluidUtil.getFluidHandler(parStack); | |
if (containerFluidHandler == null) // itemstack not really a fluid handler | |
{ | |
// DEBUG | |
System.out.println("Item stack not really a fluid handling container"); | |
return resultFail; | |
} | |
else // itemstack is a valid fluid handler | |
{ | |
// DEBUG | |
System.out.println("Item stack has a fluid handler"); | |
FluidStack containerFluidStack = getFluidStack(parStack); | |
if (containerFluidStack == null || containerFluidStack.amount <= 0) // not actual fluid stack in container | |
{ | |
// DEBUG | |
System.out.println("No actual fluid in container"); | |
return resultFail; | |
} | |
else // there is actual fluid stack in container | |
{ | |
// DEBUG | |
System.out.println("There is a fluid stack in the container"); | |
Fluid fluid = containerFluidStack.getFluid(); | |
if (fluid == null ) // no fluid associated with fluid stack | |
{ | |
// DEBUG | |
System.out.println("Malformed fluid stack has null fluid"); | |
return resultFail; | |
} | |
else // fluid associated with fluid stack | |
{ | |
if (!fluid.canBePlacedInWorld()) // fluid cannot be placed in world | |
{ | |
// DEBUG | |
System.out.println("Fluid type doesn't allow placement in world"); | |
return resultFail; | |
} | |
else // fluid can be placed in world | |
{ | |
// DEBUG | |
System.out.println("Fluid type allows placement in world"); | |
// check that we can place the fluid at the destination | |
IBlockState destBlockState = parWorld.getBlockState(parPos); | |
if (!parWorld.isAirBlock(parPos) && destBlockState.getMaterial().isSolid() && !destBlockState.getBlock().isReplaceable(parWorld, parPos)) | |
{ | |
// DEBUG | |
System.out.println("Location is not replaceable"); | |
return resultFail; // Non-air, solid, unreplacable block. We can't put fluid here. | |
} | |
else // location is placeable | |
{ | |
// DEBUG | |
System.out.println("Location is replaceable"); | |
if (parWorld.provider.doesWaterVaporize() && fluid.doesVaporize(containerFluidStack)) | |
{ | |
fluid.vaporize(parPlayer, parWorld, parPos, containerFluidStack); | |
return ActionResult.newResult(EnumActionResult.SUCCESS, parStack); | |
} | |
else // fluid does not vaporize | |
{ | |
// This fluid handler places the fluid block when filled | |
Block blockToPlace = fluid.getBlock(); | |
IFluidHandler blockFluidHandler; | |
if (blockToPlace instanceof IFluidBlock) | |
{ | |
blockFluidHandler = new FluidBlockWrapper((IFluidBlock) blockToPlace, parWorld, parPos); | |
} | |
else if (blockToPlace instanceof BlockLiquid) | |
{ | |
blockFluidHandler = new BlockLiquidWrapper((BlockLiquid) blockToPlace, parWorld, parPos); | |
} | |
else | |
{ | |
blockFluidHandler = new BlockWrapper(blockToPlace, parWorld, parPos); | |
} | |
// actually transfer fluid | |
int blockCapacity = blockFluidHandler.getTankProperties()[0].getCapacity(); | |
int amountInContainer = containerFluidStack.amount; | |
FluidStack blockFluidStack = blockFluidHandler.getTankProperties()[0].getContents(); | |
if (blockFluidStack == null) | |
{ | |
// DEBUG | |
System.out.println("Block fluid stack is null"); | |
return resultFail; | |
} | |
else // non-null fluid stack | |
{ | |
// DEBUG | |
System.out.println("Before transferring fluids amount in container = "+amountInContainer+" and block capacity = "+blockCapacity); | |
// transfer amounts and handle cases of differences between amounts and capacities | |
if (amountInContainer > blockCapacity) // more than enough fluid to fill block | |
{ | |
containerFluidStack.amount -= blockCapacity; | |
blockFluidStack.amount = blockCapacity; | |
} | |
else // all fluid in container can fit within block | |
{ | |
blockFluidStack.amount = amountInContainer; | |
containerFluidStack.amount = 0; | |
} | |
// DEBUG | |
System.out.println("After transferring amount in container = "+containerFluidStack.amount+" and amount in block = "+blockFluidStack.amount); | |
SoundEvent soundevent = fluid.getEmptySound(containerFluidStack); | |
parWorld.playSound(parPlayer, parPos, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F); | |
if (!parPlayer.capabilities.isCreativeMode) | |
{ | |
// DEBUG | |
System.out.println("Not in creative so draining container"); | |
// success! | |
parPlayer.addStat(StatList.getObjectUseStats(this)); | |
// clamp value to non-negative | |
if (containerFluidStack.amount <= 0) | |
{ | |
containerFluidStack.amount = 0; | |
// DEBUG | |
System.out.println("fully drained the container so returning empty container"); | |
} | |
// update tag data | |
updateFluidNBT(parStack, containerFluidStack); | |
// send packet to update player | |
sendUpdatePacketToClient(parPlayer); | |
// DEBUG | |
System.out.println("After transfer block fluid stack = "+blockFluidStack.getFluid()+" "+blockFluidStack.amount+" and container fluid stack now = "+containerFluidStack.getFluid()+" "+containerFluidStack.amount); | |
parWorld.setBlockState(parPos, blockToPlace.getDefaultState()); | |
// DEBUG | |
System.out.println("Placing fluid was a success"); | |
return ActionResult.newResult(EnumActionResult.SUCCESS, containerFluidHandler.getContainer()); | |
} | |
else // in creative mode so don't use up stack | |
{ | |
// restore amount | |
containerFluidStack.amount = amountInContainer; | |
parWorld.setBlockState(parPos, blockToPlace.getDefaultState()); | |
// DEBUG | |
System.out.println("Placing fluid was a success"); | |
return resultPass; // not really sure why fail, but consistent with universal bucket | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
private void sendUpdatePacketToClient(EntityPlayer parPlayer) | |
{ | |
if (parPlayer instanceof EntityPlayerMP) | |
{ | |
// DEBUG | |
System.out.println("Sending player inventory update"); | |
((EntityPlayerMP)parPlayer).connection.sendPacket(new SPacketHeldItemChange(parPlayer.inventory.currentItem)); | |
} | |
else | |
{ | |
// do nothing | |
} | |
} | |
private void updateFluidNBT(ItemStack parItemStack, FluidStack parFluidStack) | |
{ | |
if (!parItemStack.hasTagCompound()) | |
{ | |
parItemStack.setTagCompound(new NBTTagCompound()); | |
} | |
NBTTagCompound fluidTag = new NBTTagCompound(); | |
parFluidStack.writeToNBT(fluidTag); | |
parItemStack.getTagCompound().setTag(FluidHandlerItemStack.FLUID_NBT_KEY, fluidTag); | |
// DEBUG | |
System.out.println("Wrote fluid tag to container item stack = "+fluidTag); | |
} | |
/** | |
* Gets the matching fluid stack. | |
* | |
* @param sourceHandler the source handler | |
* @param parFluid the par fluid | |
* @return the matching fluid stack | |
*/ | |
@Nullable | |
public FluidStack getMatchingFluidStack(IFluidHandler sourceHandler, Fluid parFluid) | |
{ | |
// Theoretically a tank may contain mulitple fluid stacks | |
// grab first one that matches fluid type | |
IFluidTankProperties[] tankProperties = sourceHandler.getTankProperties(); | |
FluidStack result = null; | |
for (int i=0; i < tankProperties.length; i++) | |
{ | |
if (tankProperties[i].getContents().getFluid() == parFluid) | |
{ | |
result = tankProperties[i].getContents(); | |
} | |
else | |
{ | |
// do nothing | |
} | |
} | |
return result; | |
} | |
/** | |
* Gets the fluid stack. | |
* | |
* @param container the container | |
* @return the fluid stack | |
*/ | |
@Nullable | |
public FluidStack getFluidStack(final ItemStack container) | |
{ | |
if (container.hasTagCompound() && container.getTagCompound().hasKey(FluidHandlerItemStack.FLUID_NBT_KEY)) { | |
return FluidStack.loadFluidStackFromNBT(container.getTagCompound().getCompoundTag(FluidHandlerItemStack.FLUID_NBT_KEY)); | |
} | |
return null; | |
} | |
/** | |
* Try fill alt. | |
* | |
* @param parWorld the par world | |
* @param parPlayer the par player | |
* @param mop the mop | |
* @param parContainerStack the par container stack | |
* @return the action result | |
*/ | |
public ActionResult<ItemStack> tryFillAlt(World parWorld, EntityPlayer parPlayer, RayTraceResult mop, ItemStack parContainerStack) | |
{ | |
ActionResult<ItemStack> resultPass = new ActionResult<ItemStack>(EnumActionResult.PASS, parContainerStack); | |
ActionResult<ItemStack> resultFail = new ActionResult<ItemStack>(EnumActionResult.FAIL, parContainerStack); | |
BlockPos blockPos = mop.getBlockPos(); | |
if (parWorld == null || blockPos == null || parContainerStack.isEmpty()) | |
{ | |
// DEBUG | |
System.out.println("invalid parameters (null or empty"); | |
return resultPass; | |
} | |
else // parameters are valid | |
{ | |
// that there is fluid or liquid block at the position | |
Block block = parWorld.getBlockState(blockPos).getBlock(); | |
if (block instanceof IFluidBlock || block instanceof BlockLiquid) | |
{ | |
IFluidHandler sourceFluidHandler = FluidUtil.getFluidHandler(parWorld, blockPos, mop.sideHit); | |
if (sourceFluidHandler != null) // valid fluid block | |
{ | |
// DEBUG | |
System.out.println("Found valid fluid block"); | |
IFluidHandlerItem containerFluidHandler = FluidUtil.getFluidHandler(parContainerStack); | |
if (containerFluidHandler != null) // valid fluid item | |
{ | |
// DEBUG | |
System.out.println("With valid fluid item"); | |
FluidStack containerFluidStack = getFluidStack(parContainerStack); | |
int amountRoomInContainer = CAPACITY - containerFluidStack.amount; | |
if (amountRoomInContainer <= 0) | |
{ | |
// DEBUG | |
System.out.println("No room in container, already full"); | |
return resultPass; | |
} | |
else // room in container | |
{ | |
// DEBUG | |
System.out.println("There is room in the container"); | |
FluidStack sourceFluidStack = getMatchingFluidStack(sourceFluidHandler, ModFluids.SLIME); | |
if (sourceFluidStack != null) | |
{ | |
int amountInSource = sourceFluidStack.amount; | |
if (amountInSource <= 0) // not enough fluid in source | |
{ | |
// DEBUG | |
System.out.println("Not enough fluid in source"); | |
return resultPass; | |
} | |
else // some fluid in source | |
{ | |
// DEBUG | |
System.out.println("There is some fluid in source"); | |
System.out.println("Before transfer source fluid stack = "+sourceFluidStack.getFluid()+" "+sourceFluidStack.amount+" and container fluid stack now = "+containerFluidStack.getFluid()+" "+containerFluidStack.amount); | |
// check whether enough to fill container with some to spare | |
if (sourceFluidStack.amount > amountRoomInContainer) // some to spare | |
{ | |
containerFluidStack.amount = CAPACITY; | |
sourceFluidStack.amount -= amountRoomInContainer; | |
} | |
else // no extra in source after filling containder | |
{ | |
containerFluidStack.amount = sourceFluidStack.amount; | |
sourceFluidStack.amount = 0; // used all source amount | |
parWorld.setBlockToAir(blockPos); | |
} | |
SoundEvent soundevent = containerFluidStack.getFluid().getFillSound(containerFluidStack); | |
parPlayer.playSound(soundevent, 1f, 1f); | |
// update tag data | |
updateFluidNBT(parContainerStack, containerFluidStack); | |
// send packet to update player | |
sendUpdatePacketToClient(parPlayer); | |
// DEBUG | |
System.out.println("After transfer source fluid stack = "+sourceFluidStack.getFluid()+" "+sourceFluidStack.amount+" and container fluid stack now = "+containerFluidStack.getFluid()+" "+containerFluidStack.amount); | |
return ActionResult.newResult(EnumActionResult.SUCCESS, containerFluidHandler.getContainer()); | |
} | |
} | |
else // could not find fluid in block that matches itemstack | |
{ | |
// DEBUG | |
System.out.println("No matching fluid in block"); | |
return resultPass; | |
} | |
} | |
} | |
else // not a proper fluid item | |
{ | |
// DEBUG | |
System.out.println("Malformed fluid item at position "+parContainerStack); | |
return resultFail; | |
} | |
} | |
else // not a proper fluid block | |
{ | |
// DEBUG | |
System.out.println("Malformed fluid block at position = "+blockPos); | |
return resultFail; | |
} | |
} | |
else | |
{ | |
// DEBUG | |
System.out.println("Not a fluid block in that location"); | |
return resultPass; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment