diff --git a/src/main/java/gregtech/api/metatileentity/implementations/MTEMultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/MTEMultiBlockBase.java index 98b41a62f21..1d5e58d7826 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/MTEMultiBlockBase.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/MTEMultiBlockBase.java @@ -2370,7 +2370,11 @@ protected List getFluidOutputS public boolean canDumpItemToME() { for (MTEHatch tHatch : validMTEList(mOutputBusses)) { if (tHatch instanceof MTEHatchOutputBusME) { - if ((((MTEHatchOutputBusME) tHatch).canAcceptItem())) { + if (((MTEHatchOutputBusME) tHatch).isLocked()) { + return false; + } + + if (((MTEHatchOutputBusME) tHatch).canAcceptItem()) { return true; } } @@ -2382,7 +2386,11 @@ public boolean canDumpItemToME() { public boolean canDumpFluidToME() { for (IFluidStore tHatch : getFluidOutputSlots(new FluidStack[0])) { if (tHatch instanceof MTEHatchOutputME) { - if ((((MTEHatchOutputME) tHatch).canAcceptFluid())) { + if (((MTEHatchOutputME) tHatch).isFluidLocked()) { + return false; + } + + if (((MTEHatchOutputME) tHatch).canAcceptFluid()) { return true; } } diff --git a/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputBusME.java b/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputBusME.java index 5a250eae001..a9e0d5721ea 100644 --- a/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputBusME.java +++ b/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputBusME.java @@ -11,6 +11,11 @@ import javax.annotation.Nullable; +import appeng.api.implementations.items.IStorageCell; +import appeng.items.contents.CellConfig; +import com.glodblock.github.common.item.FCBaseItemCell; +import com.glodblock.github.common.storage.IStorageFluidCell; +import com.gtnewhorizons.modularui.api.forge.ItemHandlerHelper; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -21,6 +26,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -57,9 +63,11 @@ import gregtech.api.util.GTUtility; import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidContainerItem; public class MTEHatchOutputBusME extends MTEHatchOutputBus implements IPowerChannelState { - protected static final long DEFAULT_CAPACITY = 1_600; protected long baseCapacity = DEFAULT_CAPACITY; @@ -72,6 +80,8 @@ public class MTEHatchOutputBusME extends MTEHatchOutputBus implements IPowerChan long lastInputTick = 0; long tickCounter = 0; boolean additionalConnection = false; + EntityPlayer lastClickedPlayer = null; + List lockedItems = new ArrayList<>(); public MTEHatchOutputBusME(int aID, String aName, String aNameRegional) { super( @@ -81,7 +91,8 @@ public MTEHatchOutputBusME(int aID, String aName, String aNameRegional) { 3, new String[] { "Item Output for Multiblocks", "Stores directly into ME", "Can cache 1600 items by default", "Change cache size by inserting a storage cell", - "Change ME connection behavior by right-clicking with wire cutter" }, + "Change ME connection behavior by right-clicking with wire cutter", + "To set output item filter, place an ME Disk that has the items in its filter settings into the slot"}, 1); } @@ -146,6 +157,22 @@ public boolean canAcceptItem() { * @return amount of items left over */ public int store(final ItemStack stack) { + if (!lockedItems.isEmpty()) { + boolean isOk = false; + + for (ItemStack lockedItem : lockedItems) { + if (lockedItem.isItemEqual(stack)) { + isOk = true; + + break; + } + } + + if (!isOk) { + return stack.stackSize; + } + } + // Always allow insertion on the same tick so we can output the entire recipe if (canAcceptItem() || (lastInputTick == tickCounter)) { itemCache.add( @@ -183,6 +210,8 @@ public void onFacingChange() { @Override public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { + this.lastClickedPlayer = aPlayer; + GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer); return true; } @@ -257,6 +286,8 @@ public boolean isActive() { @Override public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + checkItemLock(); + if (getBaseMetaTileEntity().isServerSide()) { tickCounter = aTick; if (tickCounter > (lastOutputTick + 40)) flushCachedStack(); @@ -266,8 +297,63 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { } @Override - public void addAdditionalTooltipInformation(ItemStack stack, List tooltip) { + public boolean isLocked() { + return !this.lockedItems.isEmpty(); + } + + private void checkItemLock() { + ItemStack upgradeItemStack = mInventory[0]; + + if (upgradeItemStack != null && upgradeItemStack.getItem() instanceof ItemBasicStorageCell) { + if (this.lockedItems.isEmpty()) { + CellConfig cfg = (CellConfig) ((ItemBasicStorageCell) upgradeItemStack.getItem()).getConfigInventory(upgradeItemStack); + + if (!cfg.isEmpty()) { + StringBuilder builder = new StringBuilder(); + + boolean hadFilters = false; + boolean isFirst = true; + + for (int i = 0; i < cfg.getSizeInventory(); i++) { + ItemStack stack = cfg.getStackInSlot(i); + + if (stack != null) { + hadFilters = true; + + lockedItems.add(ItemHandlerHelper.copyStackWithSize(stack, 1)); + + if (isFirst) { + builder.append(stack.getDisplayName()); + isFirst = false; + } else { + builder.append(", ").append(stack.getDisplayName()); + } + } + } + + if (hadFilters) { + if (lastClickedPlayer != null) { + GTUtility.sendChatToPlayer(lastClickedPlayer, StatCollector.translateToLocalFormatted("GT5U.hatch.item.filterchat", builder)); + } + + markDirty(); + } + } + } + } else { + if (!this.lockedItems.isEmpty()) { + this.lockedItems.clear(); + + markDirty(); + + GTUtility.sendChatToPlayer(lastClickedPlayer, "Fluid lock disabled"); + } + } + } + + @Override + public void addAdditionalTooltipInformation(ItemStack stack, List tooltip) { if (stack.hasTagCompound() && stack.stackTagCompound.hasKey("baseCapacity")) { tooltip.add( "Current cache capacity: " + EnumChatFormatting.YELLOW @@ -286,6 +372,16 @@ public void setItemNBT(NBTTagCompound aNBT) { public void saveNBTData(NBTTagCompound aNBT) { super.saveNBTData(aNBT); + NBTTagList lockedItemsTag = new NBTTagList(); + + for (ItemStack stack : this.lockedItems) { + NBTTagCompound stackTag = new NBTTagCompound(); + stack.writeToNBT(stackTag); + lockedItemsTag.appendTag(stackTag); + } + + aNBT.setTag("lockedItems", lockedItemsTag); + NBTTagList items = new NBTTagList(); for (IAEItemStack s : itemCache) { if (s.getStackSize() == 0) continue; @@ -304,6 +400,15 @@ public void saveNBTData(NBTTagCompound aNBT) { public void loadNBTData(NBTTagCompound aNBT) { super.loadNBTData(aNBT); + NBTBase lockedItemsTag = aNBT.getTag("lockedItems"); + + if (lockedItemsTag instanceof NBTTagList lockedItemsList) { + for (int i = 0; i < lockedItemsList.tagCount(); i++) { + NBTTagCompound stackTag = lockedItemsList.getCompoundTagAt(i); + this.lockedItems.add(GTUtility.loadItem(stackTag)); + } + } + NBTBase t = aNBT.getTag("cachedStack"); // legacy if (t instanceof NBTTagCompound) itemCache.add( AEApi.instance() diff --git a/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputME.java b/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputME.java index a9208d0e63a..134d41c7fbd 100644 --- a/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputME.java +++ b/src/main/java/gregtech/common/tileentities/machines/MTEHatchOutputME.java @@ -11,6 +11,7 @@ import javax.annotation.Nullable; +import appeng.items.contents.CellConfig; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -21,8 +22,10 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidStack; import com.glodblock.github.common.item.FCBaseItemCell; @@ -64,9 +67,10 @@ import gregtech.api.util.GTUtility; import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; +import net.minecraftforge.fluids.IFluidContainerItem; +import org.jetbrains.annotations.NotNull; public class MTEHatchOutputME extends MTEHatchOutput implements IPowerChannelState { - private static final long DEFAULT_CAPACITY = 128_000; private long baseCapacity = DEFAULT_CAPACITY; @@ -79,6 +83,8 @@ public class MTEHatchOutputME extends MTEHatchOutput implements IPowerChannelSta long lastInputTick = 0; long tickCounter = 0; boolean additionalConnection = false; + EntityPlayer lastClickedPlayer = null; + List lockedFluids = new ArrayList<>(); public MTEHatchOutputME(int aID, String aName, String aNameRegional) { super( @@ -88,7 +94,8 @@ public MTEHatchOutputME(int aID, String aName, String aNameRegional) { 3, new String[] { "Fluid Output for Multiblocks", "Stores directly into ME", "Can cache up to 128kL of fluids by default", "Change cache size by inserting a fluid storage cell", - "Change ME connection behavior by right-clicking with wire cutter" }, + "Change ME connection behavior by right-clicking with wire cutter", + "To set output fluid filter, place an ME Disk that has the fluids in its filter settings into the slot" }, 1); } @@ -132,6 +139,90 @@ public int fill(FluidStack aFluid, boolean doFill) { } } + @Override + public boolean canStoreFluid(@NotNull FluidStack fluidStack) { + if (!isFluidLocked()) { + return true; + } + + for (String lockedFluid : lockedFluids) { + if (lockedFluid.equals(fluidStack.getFluid().getName())) { + return true; + } + } + + return false; + } + + @Override + public boolean isFluidLocked() { + return this.mMode == 10; + } + + private void checkFluidLock() { + ItemStack upgradeItemStack = mInventory[0]; + + if (upgradeItemStack != null && upgradeItemStack.getItem() instanceof IStorageFluidCell) { + if (this.mMode == 0) { + CellConfig cfg = (CellConfig) ((FCBaseItemCell) upgradeItemStack.getItem()).getConfigInventory(upgradeItemStack); + + if (!cfg.isEmpty()) { + StringBuilder builder = new StringBuilder(); + + boolean hadFilters = false; + boolean isFirst = true; + + lockedFluids.clear(); + + for (int i = 0; i < cfg.getSizeInventory(); i++) { + ItemStack stack = cfg.getStackInSlot(i); + + if (stack == null) continue; + + FluidStack tFluid = FluidContainerRegistry.getFluidForFilledItem(stack); + + if (tFluid == null && stack.getItem() instanceof IFluidContainerItem) + tFluid = ((IFluidContainerItem) stack.getItem()).getFluid(stack); + + if (tFluid != null) { + hadFilters = true; + + lockedFluids.add(tFluid.getFluid().getName()); + + if (isFirst) { + builder.append(tFluid.getLocalizedName()); + + isFirst = false; + } else { + builder.append(", ").append(tFluid.getLocalizedName()); + } + } + } + + if (hadFilters) { + if (lastClickedPlayer != null) { + GTUtility.sendChatToPlayer(lastClickedPlayer, StatCollector.translateToLocalFormatted("GT5U.hatch.fluid.filterchat", builder)); + } + + this.mMode = 10; + + markDirty(); + } + } + } + } else { + if (this.mMode == 10) { + lockedFluids.clear(); + + this.mMode = 0; + + markDirty(); + + GTUtility.sendChatToPlayer(lastClickedPlayer, "Fluid lock disabled"); + } + } + } + @Override public int getCapacity() { return 0; @@ -160,6 +251,11 @@ public boolean canAcceptFluid() { return getCachedAmount() < getCacheCapacity() || lastInputTick == tickCounter; } + @Override + public boolean isEmptyAndAcceptsAnyFluid() { + return mMode == 0; + } + /** * Attempt to store fluid in connected ME network. Returns how much fluid is accepted (if the network was down e.g.) * @@ -206,6 +302,9 @@ public void onFacingChange() { @Override public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer); + + lastClickedPlayer = aPlayer; + return true; } @@ -221,9 +320,7 @@ public boolean doesFillContainers() { @Override public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { - // Don't allow to lock fluid in me fluid hatch - if (!getBaseMetaTileEntity().getCoverInfoAtSide(side) - .isGUIClickable()) return; + if (!getBaseMetaTileEntity().getCoverInfoAtSide(side).isGUIClickable()) return; } @Override @@ -294,12 +391,14 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { if (tickCounter > (lastOutputTick + 40)) flushCachedStack(); if (tickCounter % 20 == 0) getBaseMetaTileEntity().setActive(isActive()); } + + checkFluidLock(); + super.onPostTick(aBaseMetaTileEntity, aTick); } @Override public void addAdditionalTooltipInformation(ItemStack stack, List tooltip) { - if (stack.hasTagCompound() && stack.stackTagCompound.hasKey("baseCapacity")) { tooltip.add( "Current cache capacity: " + EnumChatFormatting.YELLOW @@ -401,6 +500,17 @@ public void setItemNBT(NBTTagCompound aNBT) { @Override public void saveNBTData(NBTTagCompound aNBT) { super.saveNBTData(aNBT); + + NBTTagList lockedFluidsTag = new NBTTagList(); + + for (String fluid : this.lockedFluids) { + NBTTagCompound fluidTag = new NBTTagCompound(); + fluidTag.setString("fluid", fluid); + lockedFluidsTag.appendTag(fluidTag); + } + + aNBT.setTag("lockedFluids", lockedFluidsTag); + NBTTagList fluids = new NBTTagList(); for (IAEFluidStack s : fluidCache) { if (s.getStackSize() == 0) continue; @@ -421,6 +531,16 @@ public void saveNBTData(NBTTagCompound aNBT) { @Override public void loadNBTData(NBTTagCompound aNBT) { super.loadNBTData(aNBT); + + NBTBase lockedFluidsTag = aNBT.getTag("lockedFluids"); + + if (lockedFluidsTag instanceof NBTTagList lockedFluidsList) { + for (int i = 0; i < lockedFluidsList.tagCount(); i++) { + NBTTagCompound fluidTag = lockedFluidsList.getCompoundTagAt(i); + this.lockedFluids.add(fluidTag.getString("fluid")); + } + } + NBTBase t = aNBT.getTag("cachedFluids"); if (t instanceof NBTTagList l) { for (int i = 0; i < l.tagCount(); ++i) { diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang index d8618059df9..a0f16bdb7ef 100644 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ b/src/main/resources/assets/gregtech/lang/en_US.lang @@ -710,6 +710,8 @@ GT5U.hatch.infiniteCacheFluid.true=ME Output hatch will infinitely cache fluid, GT5U.hatch.infiniteCacheFluid.false=ME Output hatch will stop accepting fluid when offline for more than 2 seconds GT5U.hatch.additionalConnection.true=ME channels connect to any side GT5U.hatch.additionalConnection.false=ME channels connect to front side only +GT5U.hatch.fluid.filterchat=Outputs these specific Fluids: %s +GT5U.hatch.item.filterchat=Outputs these specific Items: %s GT5U.bus.filterTooltip.empty=§aDrag item from NEI to set output filter GT5U.bus.filterTooltip.full=§aClick to clear output filter