Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Bucket Behavior to Cells #2660

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ default EnumActionResult onItemUseFirst(EntityPlayer player, World world, BlockP

default ActionResult<ItemStack> onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand,
EnumFacing facing, float hitX, float hitY, float hitZ) {
return ActionResult.newResult(EnumActionResult.PASS, player.getHeldItem(hand));
return pass(player.getHeldItem(hand));
}

default void addInformation(ItemStack itemStack, List<String> lines) {}
Expand All @@ -50,8 +50,20 @@ default Multimap<String, AttributeModifier> getAttributeModifiers(EntityEquipmen
}

default ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
return ActionResult.newResult(EnumActionResult.PASS, player.getHeldItem(hand));
return pass(player.getHeldItem(hand));
}

default void addPropertyOverride(@NotNull Item item) {}

default ActionResult<ItemStack> pass(ItemStack stack) {
return ActionResult.newResult(EnumActionResult.PASS, stack);
}

default ActionResult<ItemStack> success(ItemStack stack) {
return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
}

default ActionResult<ItemStack> fail(ItemStack stack) {
return ActionResult.newResult(EnumActionResult.FAIL, stack);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
package gregtech.api.items.metaitem.stats;

import gregtech.api.util.GTUtility;

import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fluids.capability.wrappers.BlockLiquidWrapper;
import net.minecraftforge.fluids.capability.wrappers.BlockWrapper;
import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class ItemFluidContainer implements IItemContainerItemProvider, IItemBehaviour {

private final boolean isBucket;

public class ItemFluidContainer implements IItemContainerItemProvider {
public ItemFluidContainer(boolean isBucket) {
this.isBucket = isBucket;
}

public ItemFluidContainer() {
this(false);
}

@Override
public ItemStack getContainerItem(ItemStack itemStack) {
IFluidHandlerItem handler = itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);
IFluidHandlerItem handler = FluidUtil.getFluidHandler(itemStack);
if (handler != null) {
FluidStack drained = handler.drain(1000, false);
if (drained == null || drained.amount != 1000) return ItemStack.EMPTY;
Expand All @@ -18,4 +54,168 @@ public ItemStack getContainerItem(ItemStack itemStack) {
}
return itemStack;
}

@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
ItemStack stack = player.getHeldItem(hand);
if (!isBucket) return pass(stack);

ItemStack cellStack = GTUtility.copy(1, stack);

var cellHandler = FluidUtil.getFluidHandler(cellStack);
if (cellHandler == null) return pass(stack);

var result = rayTrace(world, player, true);
if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) {
return pass(stack);
}

var pos = result.getBlockPos();

// can the player modify the clicked block
if (!world.isBlockModifiable(player, pos)) {
return fail(stack);
}

// can player edit
if (!player.canPlayerEdit(pos, result.sideHit, cellStack)) {
return fail(stack);
}

// prioritize filling the cell if there's space, otherwise place fluid
if (fillCell(cellStack, world, pos, result.sideHit, player)) {
addToPlayerInventory(stack, cellHandler.getContainer(), player, hand);
M-W-K marked this conversation as resolved.
Show resolved Hide resolved
return success(stack);

} else {
result = rayTrace(world, player, false);
if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) {
return pass(stack);
}
pos = result.getBlockPos();

if (tryPlace(cellHandler, world, pos.offset(result.sideHit), result.sideHit, player)) {
addToPlayerInventory(stack, cellHandler.getContainer(), player, hand);
return success(stack);
}
}

return pass(stack);
}

private static boolean tryPlace(IFluidHandlerItem cellHandler, World world, BlockPos pos, EnumFacing side,
EntityPlayer player) {
var cellFluid = cellHandler.drain(Fluid.BUCKET_VOLUME, false);
if (cellFluid == null || !cellFluid.getFluid().canBePlacedInWorld())
return false;

IFluidHandler blockHandler = getOrCreate(cellFluid, world, pos, side);

// 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) {
// Non-air, solid, unreplacable block. We can't put fluid here.
return false;
}

// check vaporize
if (world.provider.doesWaterVaporize() && cellFluid.getFluid().doesVaporize(cellFluid)) {
cellHandler.drain(Fluid.BUCKET_VOLUME, true);
cellFluid.getFluid().vaporize(player, world, pos, cellFluid);
return true;
}

// fill block
int filled = blockHandler.fill(cellFluid, false);

if (filled != Fluid.BUCKET_VOLUME) return false;

playSound(cellFluid, true, player);
boolean consume = !player.isSpectator() && !player.isCreative();
blockHandler.fill(cellHandler.drain(Fluid.BUCKET_VOLUME, consume), true);
return true;
}

private static boolean fillCell(ItemStack cellStack, World world, BlockPos pos, EnumFacing side,
EntityPlayer player) {
IFluidHandler blockHandler = FluidUtil.getFluidHandler(world, pos, side);
if (blockHandler == null) return false;

IFluidHandlerItem cellHandler = FluidUtil.getFluidHandler(cellStack);
if (cellHandler == null) return false;

FluidStack stack = blockHandler.drain(Fluid.BUCKET_VOLUME, false);
int filled = cellHandler.fill(stack, false);

if (filled != Fluid.BUCKET_VOLUME) return false;

playSound(stack, false, player);
boolean consume = !player.isSpectator() && !player.isCreative();
cellHandler.fill(blockHandler.drain(Fluid.BUCKET_VOLUME, true), consume);
return true;
}

// copied and adapted from Item.java
@Nullable
private static RayTraceResult rayTrace(World worldIn, EntityPlayer player, boolean hitFluids) {
Vec3d lookPos = player.getPositionVector()
.add(0, player.getEyeHeight(), 0);

Vec3d lookOffset = player.getLookVec()
.scale(player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue());

return worldIn.rayTraceBlocks(lookPos, lookPos.add(lookOffset),
hitFluids, !hitFluids, false);
}

@NotNull
private static IFluidHandler createHandler(FluidStack stack, World world, BlockPos pos) {
Block block = stack.getFluid().getBlock();
if (block instanceof IFluidBlock) {
return new FluidBlockWrapper((IFluidBlock) block, world, pos);
} else if (block instanceof BlockLiquid) {
return new BlockLiquidWrapper((BlockLiquid) block, world, pos);
} else {
return new BlockWrapper(block, world, pos);
}
}

private static IFluidHandler getOrCreate(FluidStack stack, World world, BlockPos pos, EnumFacing side) {
IFluidHandler handler = FluidUtil.getFluidHandler(world, pos, side);
if (handler != null) return handler;
return createHandler(stack, world, pos);
}

private static void addToPlayerInventory(ItemStack playerStack, ItemStack resultStack, EntityPlayer player,
EnumHand hand) {
if (playerStack.getCount() > resultStack.getCount()) {
playerStack.shrink(resultStack.getCount());
if (!player.inventory.addItemStackToInventory(resultStack) && !player.world.isRemote) {
EntityItem dropItem = player.entityDropItem(resultStack, 0);
if (dropItem != null) dropItem.setPickupDelay(0);
}
} else {
player.setHeldItem(hand, resultStack);
}
}

/**
* Play the appropriate fluid interaction sound for the fluid. <br />
* Must be called on server to work correctly
**/
private static void playSound(FluidStack fluid, boolean fill, EntityPlayer player) {
if (fluid == null || player.world.isRemote) return;
SoundEvent soundEvent;
if (fill) {
soundEvent = fluid.getFluid().getFillSound(fluid);
} else {
soundEvent = fluid.getFluid().getEmptySound(fluid);
}
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ,
soundEvent, SoundCategory.PLAYERS, 1.0F, 1.0F);
}
}
19 changes: 12 additions & 7 deletions src/main/java/gregtech/common/items/MetaItem1.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,46 +191,51 @@ public void registerSubItems() {
// Fluid Cells: ID 78-88
FLUID_CELL = addItem(78, "fluid_cell")
.addComponents(new FilteredFluidStats(1000, 1800, true, false, false, false, false),
new ItemFluidContainer())
new ItemFluidContainer(true))
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_UNIVERSAL = addItem(79, "fluid_cell.universal")
.addComponents(new FilteredFluidStats(1000, 1800, true, false, false, false, true),
new ItemFluidContainer())
new ItemFluidContainer(true))
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_LARGE_STEEL = addItem(80, "large_fluid_cell.steel")
.addComponents(new FilteredFluidStats(8000,
Materials.Steel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, false,
false, false, true), new ItemFluidContainer())
false, false, true),
new ItemFluidContainer(true))
.setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, M * 4))) // ingot * 4
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_LARGE_ALUMINIUM = addItem(81, "large_fluid_cell.aluminium")
.addComponents(new FilteredFluidStats(32000,
Materials.Aluminium.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, false,
false, false, true), new ItemFluidContainer())
false, false, true),
new ItemFluidContainer(true))
.setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Aluminium, M * 4))) // ingot * 4
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_LARGE_STAINLESS_STEEL = addItem(82, "large_fluid_cell.stainless_steel")
.addComponents(new FilteredFluidStats(64000,
Materials.StainlessSteel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true,
true, true, false, true), new ItemFluidContainer())
true, true, false, true),
new ItemFluidContainer(true))
.setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.StainlessSteel, M * 6))) // ingot * 6
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_LARGE_TITANIUM = addItem(83, "large_fluid_cell.titanium")
.addComponents(new FilteredFluidStats(128000,
Materials.Titanium.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, true,
false, false, true), new ItemFluidContainer())
false, false, true),
new ItemFluidContainer(true))
.setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Titanium, M * 6))) // ingot * 6
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

FLUID_CELL_LARGE_TUNGSTEN_STEEL = addItem(84, "large_fluid_cell.tungstensteel")
.addComponents(new FilteredFluidStats(512000,
Materials.TungstenSteel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true,
true, false, false, true), new ItemFluidContainer())
true, false, false, true),
new ItemFluidContainer(true))
.setMaxStackSize(32)
.setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.TungstenSteel, M * 8))) // ingot * 8
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);
Expand Down