diff --git a/src/main/java/gregtech/api/capability/GregtechCapabilities.java b/src/main/java/gregtech/api/capability/GregtechCapabilities.java index 7e9d215470..6d576c9197 100644 --- a/src/main/java/gregtech/api/capability/GregtechCapabilities.java +++ b/src/main/java/gregtech/api/capability/GregtechCapabilities.java @@ -26,4 +26,7 @@ public class GregtechCapabilities { @CapabilityInject(IFuelable.class) public static Capability CAPABILITY_FUELABLE = null; + @CapabilityInject(IFluidVoiding.class) + public static Capability CAPABILITY_FLUID_VOIDING = null; + } diff --git a/src/main/java/gregtech/api/capability/IFluidVoiding.java b/src/main/java/gregtech/api/capability/IFluidVoiding.java new file mode 100644 index 0000000000..37df8d81ae --- /dev/null +++ b/src/main/java/gregtech/api/capability/IFluidVoiding.java @@ -0,0 +1,12 @@ +package gregtech.api.capability; + +import net.minecraftforge.fluids.FluidStack; + +import java.util.function.Predicate; + +public interface IFluidVoiding { + + int voidingAmount(); + + Predicate checkInputFluid(); +} diff --git a/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java b/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java index b768c06790..647cd804a0 100644 --- a/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java +++ b/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java @@ -39,6 +39,7 @@ public static void init() { registerCapabilityWithNoDefault(ICoverable.class); registerCapabilityWithNoDefault(IControllable.class); registerCapabilityWithNoDefault(IFuelable.class); + registerCapabilityWithNoDefault(IFluidVoiding.class); registerCapabilityWithNoDefault(IWrenchItem.class); registerCapabilityWithNoDefault(IScrewdriverItem.class); diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 7391ea42dc..586cdd68c7 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -10,8 +10,10 @@ import codechicken.lib.vec.Matrix4; import com.google.common.base.Preconditions; import gregtech.api.GregTechAPI; +import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IEnergyContainer; +import gregtech.api.capability.IFluidVoiding; import gregtech.api.capability.impl.FluidHandlerProxy; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.capability.impl.ItemHandlerProxy; @@ -55,6 +57,7 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import java.util.function.Predicate; import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; @@ -843,16 +846,35 @@ public void pushFluidsIntoNearbyHandlers(EnumFacing... allowedFaces) { for (EnumFacing nearbyFacing : allowedFaces) { blockPos.setPos(getPos()).move(nearbyFacing); TileEntity tileEntity = getWorld().getTileEntity(blockPos); - if (tileEntity == null) { + //Get the fluid voiding capability + IFluidVoiding fluidVoiding = getCoverCapability(GregtechCapabilities.CAPABILITY_FLUID_VOIDING, nearbyFacing); + //Allow the fluid voiding cover to take fluids, but not be a tile entity + if (tileEntity == null && fluidVoiding == null) { continue; } - IFluidHandler fluidHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, nearbyFacing.getOpposite()); + //Get the capability of the source machine + IFluidHandler machineFluidHandler = getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, nearbyFacing); + + //Get the capability of the destination TE + IFluidHandler destinationTE = null; + if(tileEntity != null) { + destinationTE = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, nearbyFacing.getOpposite()); + } + //use getCoverCapability so fluid tank index filtering and fluid filtering covers will work properly - IFluidHandler myFluidHandler = getCoverCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, nearbyFacing); - if (fluidHandler == null || myFluidHandler == null) { + IFluidHandler coverFluidHandler = getCoverCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, nearbyFacing); + if (destinationTE == null && coverFluidHandler == null) { continue; } - GTFluidUtils.transferFluids(myFluidHandler, fluidHandler, Integer.MAX_VALUE); + if(fluidVoiding != null && destinationTE != null) { + List>> transferList = new ArrayList<>(); + transferList.add(new Tuple<>(coverFluidHandler, fluidVoiding.checkInputFluid())); + transferList.add(new Tuple<>(destinationTE, fluidStack -> true)); + GTFluidUtils.transferFluidsToMultipleHandlers(machineFluidHandler, transferList, Integer.MAX_VALUE); + } + else if(destinationTE != null){ + GTFluidUtils.transferFluids(coverFluidHandler, destinationTE, Integer.MAX_VALUE); + } } blockPos.release(); } @@ -1204,4 +1226,4 @@ public float getBlockHardness() { public float getBlockResistance() { return 6.0f; } -} \ No newline at end of file +} diff --git a/src/main/java/gregtech/api/util/GTFluidUtils.java b/src/main/java/gregtech/api/util/GTFluidUtils.java index 5fba17e4ad..dd4260091a 100644 --- a/src/main/java/gregtech/api/util/GTFluidUtils.java +++ b/src/main/java/gregtech/api/util/GTFluidUtils.java @@ -1,10 +1,13 @@ package gregtech.api.util; +import net.minecraft.util.Tuple; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; import java.util.function.Predicate; public class GTFluidUtils { @@ -14,34 +17,58 @@ public static int transferFluids(@Nonnull IFluidHandler sourceHandler, @Nonnull } public static int transferFluids(@Nonnull IFluidHandler sourceHandler, @Nonnull IFluidHandler destHandler, int transferLimit, @Nonnull Predicate fluidFilter) { + + List>> transferSet = new ArrayList<>(); + transferSet.add(new Tuple<>(destHandler, fluidFilter)); + return transferFluidsToMultipleHandlers(sourceHandler, transferSet, transferLimit); + } + + /** + Used to void fluids through the fluid voiding filter before transferring any non voided fluids into a neighboring fluid handler + destHandler is an array of fluid handlers, with the handler of the voiding fluid cover first + **/ + public static int transferFluidsToMultipleHandlers(@Nonnull IFluidHandler sourceHandler, @Nonnull List>> transferTuple, int transferLimit) { + + int fluidLeftToTransfer = transferLimit; - for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { - FluidStack currentFluid = tankProperties.getContents(); - if (currentFluid == null || currentFluid.amount == 0 || !fluidFilter.test(currentFluid)) { - continue; - } + for(Tuple> transfer : transferTuple) { - currentFluid.amount = fluidLeftToTransfer; - FluidStack fluidStack = sourceHandler.drain(currentFluid, false); - if (fluidStack == null || fluidStack.amount == 0) { - continue; - } + IFluidHandler destination = transfer.getFirst(); + Predicate filter = transfer.getSecond(); - int canInsertAmount = destHandler.fill(fluidStack, false); - if (canInsertAmount > 0) { - fluidStack.amount = canInsertAmount; - fluidStack = sourceHandler.drain(fluidStack, true); - if (fluidStack != null && fluidStack.amount > 0) { - destHandler.fill(fluidStack, true); + //Check the contents of the source provider + for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { + FluidStack currentFluid = tankProperties.getContents(); + if (currentFluid == null || currentFluid.amount == 0 || (!filter.test(currentFluid))) { + continue; + } + + //Set the amount to be drained on the fluid to the maximum amount + currentFluid.amount = fluidLeftToTransfer; + //Simulate the drain to find the resultant Fluid and amount + FluidStack fluidStack = sourceHandler.drain(currentFluid, false); + if (fluidStack == null || fluidStack.amount == 0) { + continue; + } - fluidLeftToTransfer -= fluidStack.amount; - if (fluidLeftToTransfer == 0) { - break; + int canInsertAmount = destination.fill(fluidStack, false); + if (canInsertAmount > 0) { + fluidStack.amount = canInsertAmount; + fluidStack = sourceHandler.drain(fluidStack, true); + if (fluidStack != null && fluidStack.amount > 0) { + destination.fill(fluidStack, true); + + fluidLeftToTransfer -= fluidStack.amount; + if (fluidLeftToTransfer == 0) { + break; + } } } + } } + return transferLimit - fluidLeftToTransfer; } } diff --git a/src/main/java/gregtech/common/covers/CoverBehaviors.java b/src/main/java/gregtech/common/covers/CoverBehaviors.java index 58b4b04a50..8e0cc2f395 100644 --- a/src/main/java/gregtech/common/covers/CoverBehaviors.java +++ b/src/main/java/gregtech/common/covers/CoverBehaviors.java @@ -61,6 +61,8 @@ public static void init() { registerBehavior(37, new ResourceLocation(GTValues.MODID, "machine_controller"), MetaItems.COVER_MACHINE_CONTROLLER, CoverMachineController::new); registerBehavior(38, new ResourceLocation(GTValues.MODID, "smart_filter"), MetaItems.SMART_FILTER, (tile, side) -> new CoverItemFilter(tile, side, "cover.smart_item_filter.title", Textures.SMART_FILTER_FILTER_OVERLAY, new SmartItemFilter())); registerBehavior(39, new ResourceLocation(GTValues.MODID, "facade"), MetaItems.COVER_FACADE, CoverFacade::new); + + registerBehavior(40, new ResourceLocation(GTValues.MODID, "fluid_voiding"), MetaItems.COVER_FLUID_VOIDING, CoverFluidVoiding::new); } public static void registerBehavior(int coverNetworkId, ResourceLocation coverId, MetaValueItem placerItem, BiFunction behaviorCreator) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java new file mode 100644 index 0000000000..902c15aa47 --- /dev/null +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -0,0 +1,148 @@ +package gregtech.common.covers; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Matrix4; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IFluidVoiding; +import gregtech.api.capability.impl.FluidHandlerDelegate; +import gregtech.api.cover.CoverBehavior; +import gregtech.api.cover.CoverWithUI; +import gregtech.api.cover.ICoverable; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.render.Textures; +import gregtech.common.covers.filter.FluidFilterContainer; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.*; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import java.util.function.Predicate; + +public class CoverFluidVoiding extends CoverBehavior implements CoverWithUI, IFluidVoiding { + + private FluidFilterContainer fluidFilter; + protected FluidHandlerVoiding fluidHandler; + private final int voidingAmount = Integer.MAX_VALUE; + + public CoverFluidVoiding(ICoverable coverable, EnumFacing attachedSide) { + super(coverable, attachedSide); + fluidFilter = new FluidFilterContainer(this); + } + + @Override + public int voidingAmount() { + return voidingAmount; + } + + @Override + public boolean canAttach() { + return coverHolder.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, attachedSide) != null; + } + + @Override + public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, Cuboid6 plateBox, BlockRenderLayer layer) { + Textures.PUMP_OVERLAY.renderSided(attachedSide, plateBox, renderState, pipeline, translation); + } + + @Override + public void onRemoved() { + NonNullList drops = NonNullList.create(); + MetaTileEntity.clearInventory(drops, fluidFilter.getFilterInventory()); + for (ItemStack itemStack : drops) { + Block.spawnAsEntity(coverHolder.getWorld(), coverHolder.getPos(), itemStack); + } + } + + @Override + public EnumActionResult onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, CuboidRayTraceResult hitResult) { + if (!coverHolder.getWorld().isRemote) { + openUI((EntityPlayerMP) playerIn); + } + return EnumActionResult.SUCCESS; + } + + @Override + public boolean shouldCoverInteractWithOutputside() { + return true; + } + + @Override + public Predicate checkInputFluid() { + return fluidStack -> fluidFilter.testFluidStack(fluidStack); + } + + @Override + public ModularUI createUI(EntityPlayer player) { + WidgetGroup primaryGroup = new WidgetGroup(); + + primaryGroup.addWidget(new LabelWidget(10, 5, "cover.fluid_voiding.title")); + fluidFilter.initUI(88, primaryGroup::addWidget); + + return ModularUI.builder(GuiTextures.BACKGROUND, 176, 184 + 82) + .widget(primaryGroup) + .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 8, 184) + .build(this, player); + } + + @Override + public T getCapability(Capability capability, T defaultValue) { + if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + IFluidHandler delegate = (IFluidHandler) defaultValue; + if (fluidHandler == null || fluidHandler.delegate != delegate) { + this.fluidHandler = new FluidHandlerVoiding(delegate); + } + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(fluidHandler); + } + else if (capability == GregtechCapabilities.CAPABILITY_FLUID_VOIDING) { + return GregtechCapabilities.CAPABILITY_FLUID_VOIDING.cast(this); + } + return defaultValue; + } + + @Override + public void writeToNBT(NBTTagCompound tagCompound) { + super.writeToNBT(tagCompound); + tagCompound.setTag("Filter", fluidFilter.serializeNBT()); + } + + @Override + public void readFromNBT(NBTTagCompound tagCompound) { + super.readFromNBT(tagCompound); + if (tagCompound.hasKey("FluidFilter")) { + fluidFilter.deserializeNBT(tagCompound); + } else { + fluidFilter.deserializeNBT(tagCompound.getCompoundTag("Filter")); + } + + } + + public class FluidHandlerVoiding extends FluidHandlerDelegate { + + public FluidHandlerVoiding(IFluidHandler delegate) { + super(delegate); + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + if(!checkInputFluid().test(resource)) { + return 0; + } + + return voidingAmount; + } + } + +} diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index bb683e7e55..7644707711 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -279,6 +279,7 @@ public void registerSubItems() { COVER_CRAFTING = addItem(744, "cover.crafting").setInvisible(); COVER_DRAIN = addItem(745, "cover.drain").setInvisible(); + COVER_FLUID_VOIDING = addItem(748, "cover.fluid.voiding"); COVER_SHUTTER = addItem(749, "cover.shutter"); COVER_SOLAR_PANEL = addItem(750, "cover.solar.panel"); @@ -552,4 +553,4 @@ protected void addMaterialTooltip(ItemStack itemStack, OrePrefix prefix, Materia } } -} \ No newline at end of file +} diff --git a/src/main/java/gregtech/common/items/MetaItems.java b/src/main/java/gregtech/common/items/MetaItems.java index 7dc01a3865..1fedc40aaf 100644 --- a/src/main/java/gregtech/common/items/MetaItems.java +++ b/src/main/java/gregtech/common/items/MetaItems.java @@ -306,6 +306,7 @@ private MetaItems() { public static MetaItem.MetaValueItem COVER_SHUTTER; public static MetaItem.MetaValueItem COVER_MACHINE_CONTROLLER; public static MetaItem.MetaValueItem COVER_FACADE; + public static MetaItem.MetaValueItem COVER_FLUID_VOIDING; public static MetaItem.MetaValueItem COVER_ACTIVITY_DETECTOR; public static MetaItem.MetaValueItem COVER_FLUID_DETECTOR; diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index cf639f939b..64d8a9f855 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -609,6 +609,14 @@ private static void registerAssemblerRecipes() { .EUt(16).duration(200) .buildAndRegister(); + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .input(OrePrefix.plate, Materials.Steel, 4) + .input(OrePrefix.rotor, Materials.Steel, 1) + .inputs(MetaItems.ELECTRIC_MOTOR_LV.getStackForm(1)) + .outputs(COVER_FLUID_VOIDING.getStackForm(1)) + .EUt(16).duration(200) + .buildAndRegister(); + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(1800).EUt(30).input(OrePrefix.dust, Materials.EnderPearl, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Basic, 4).fluidInputs(Materials.Osmium.getFluid(L * 2)).outputs(MetaItems.FIELD_GENERATOR_LV.getStackForm()).buildAndRegister(); RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(1800).EUt(120).input(OrePrefix.dust, Materials.EnderEye, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Good, 4).fluidInputs(Materials.Osmium.getFluid(576)).outputs(MetaItems.FIELD_GENERATOR_MV.getStackForm()).buildAndRegister(); RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(1800).EUt(480).inputs(MetaItems.QUANTUM_EYE.getStackForm()).input(OrePrefix.circuit, MarkerMaterials.Tier.Advanced, 4).fluidInputs(Materials.Osmium.getFluid(1152)).outputs(MetaItems.FIELD_GENERATOR_HV.getStackForm()).buildAndRegister(); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 894d6676cc..03e6d11207 100755 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -536,6 +536,8 @@ metaitem.cover.energy.detector.name=Energy Detector metaitem.cover.energy.detector.tooltip=Gives out Energy Amount as Redstone metaitem.cover.player.detector.name=Player Detector metaitem.cover.player.detector.tooltip=Gives out close Players as Redstone +metaitem.cover.fluid.voiding.name=Fluid Voider +cover.fluid_voiding.title=Fluid Voider metaitem.cover.facade.name=%s Facade metaitem.cover.facade.tooltip=Decorative outfit diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/cover.fluid.voiding.json b/src/main/resources/assets/gregtech/models/item/metaitems/cover.fluid.voiding.json new file mode 100644 index 0000000000..f7b0e13760 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/cover.fluid.voiding.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/cover.drain" + } +}