diff --git a/dependencies.gradle b/dependencies.gradle index 445b5e3963b..49d93cc7bd5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -40,7 +40,7 @@ dependencies { // Published dependencies api("codechicken:codechickenlib:3.2.3.358") - api("com.cleanroommc:modularui:2.4.1") { transitive = false } + api("com.cleanroommc:modularui:2.4.3") { transitive = false } api("com.cleanroommc:groovyscript:0.8.0") { transitive = false } api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.684") api rfg.deobf("curse.maven:ae2-extended-life-570458:4402048") // AE2UEL 0.55.6 diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index 4fcead477d4..225e12e4f74 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -23,6 +23,9 @@ public static int assignId() { public static final int UPDATE_AUTO_OUTPUT_FLUIDS = assignId(); public static final int UPDATE_IS_VOIDING = assignId(); + // Robotic Arm + public static final int UPDATE_TRANSFER_MODE = assignId(); + // Drum public static final int UPDATE_AUTO_OUTPUT = assignId(); diff --git a/src/main/java/gregtech/api/cover/CoverWithUI.java b/src/main/java/gregtech/api/cover/CoverWithUI.java index f40f2df37bc..d8780c611d9 100644 --- a/src/main/java/gregtech/api/cover/CoverWithUI.java +++ b/src/main/java/gregtech/api/cover/CoverWithUI.java @@ -2,6 +2,7 @@ import gregtech.api.gui.IUIHolder; import gregtech.api.gui.ModularUI; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuiTheme; import gregtech.api.mui.GregTechGuiScreen; import gregtech.api.mui.factory.CoverGuiFactory; @@ -9,20 +10,25 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.util.IStringSerializable; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import com.cleanroommc.modularui.api.IGuiHolder; +import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.drawable.ItemDrawable; import com.cleanroommc.modularui.factory.SidedPosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.ModularScreen; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.MouseData; import com.cleanroommc.modularui.value.BoolValue; import com.cleanroommc.modularui.value.sync.EnumSyncValue; import com.cleanroommc.modularui.value.sync.GuiSyncManager; import com.cleanroommc.modularui.value.sync.IntSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.ApiStatus; @@ -92,13 +98,12 @@ default void markAsDirty() { /** * Create the Title bar widget for a Cover. */ - default Row createTitleRow() { - ItemStack item = getDefinition().getDropItemStack(); + static Row createTitleRow(ItemStack stack) { return new Row() .pos(4, 4) .height(16).coverChildrenWidth() - .child(new ItemDrawable(getDefinition().getDropItemStack()).asWidget().size(16).marginRight(4)) - .child(IKey.str(item.getDisplayName()).color(UI_TITLE_COLOR).asWidget().heightRel(1.0f)); + .child(new ItemDrawable(stack).asWidget().size(16).marginRight(4)) + .child(IKey.str(stack.getDisplayName()).color(UI_TITLE_COLOR).asWidget().heightRel(1.0f)); } /** @@ -108,6 +113,31 @@ default ParentWidget createSettingsRow() { return new ParentWidget<>().height(16).widthRel(1.0f).marginBottom(2); } + default int getIncrementValue(MouseData data) { + int adjust = 1; + if (data.shift) adjust *= 4; + if (data.ctrl) adjust *= 16; + if (data.alt) adjust *= 64; + return adjust; + } + + default IKey createAdjustOverlay(boolean increment) { + final StringBuilder builder = new StringBuilder(); + builder.append(increment ? '+' : '-'); + builder.append(getIncrementValue(MouseData.create(-1))); + + float scale = 1f; + if (builder.length() == 3) { + scale = 0.8f; + } else if (builder.length() == 4) { + scale = 0.6f; + } else if (builder.length() > 4) { + scale = 0.5f; + } + return IKey.str(builder.toString()) + .scale(scale); + } + /** * Get a BoolValue for use with toggle buttons which are "linked together," * meaning only one of them can be pressed at a time. @@ -123,4 +153,88 @@ default > BoolValue.Dynamic boolValueOf(EnumSyncValue syncV default BoolValue.Dynamic boolValueOf(IntSyncValue syncValue, int value) { return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); } + + class EnumRowBuilder> { + + private EnumSyncValue syncValue; + private final Class enumValue; + private String lang; + private IDrawable[] background; + private IDrawable selectedBackground; + private IDrawable[] overlay; + + public EnumRowBuilder(Class enumValue) { + this.enumValue = enumValue; + } + + public EnumRowBuilder value(EnumSyncValue syncValue) { + this.syncValue = syncValue; + return this; + } + + public EnumRowBuilder lang(String lang) { + this.lang = lang; + return this; + } + + public EnumRowBuilder background(IDrawable... background) { + this.background = background; + return this; + } + + public EnumRowBuilder selectedBackground(IDrawable selectedBackground) { + this.selectedBackground = selectedBackground; + return this; + } + + public EnumRowBuilder overlay(IDrawable... overlay) { + this.overlay = overlay; + return this; + } + + public EnumRowBuilder overlay(int size, IDrawable... overlay) { + this.overlay = new IDrawable[overlay.length]; + for (int i = 0; i < overlay.length; i++) { + this.overlay[i] = overlay[i].asIcon().size(size); + } + return this; + } + + private BoolValue.Dynamic boolValueOf(EnumSyncValue syncValue, T value) { + return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); + } + + public Row build() { + var row = new Row().marginBottom(2).coverChildrenHeight().widthRel(1f); + if (this.enumValue != null && this.syncValue != null) { + for (var enumVal : enumValue.getEnumConstants()) { + var button = new ToggleButton().size(18).marginRight(2) + .value(boolValueOf(this.syncValue, enumVal)); + + if (this.background != null && this.background.length > 0) + button.background(this.background); + else + button.background(GTGuiTextures.MC_BUTTON); + + if (this.selectedBackground != null) + button.selectedBackground(this.selectedBackground); + else + button.selectedBackground(GTGuiTextures.MC_BUTTON_DISABLED); + + if (this.overlay != null) + button.overlay(this.overlay[enumVal.ordinal()]); + + if (enumVal instanceof IStringSerializable serializable) { + button.addTooltipLine(IKey.lang(serializable.getName())); + } + row.child(button); + } + } + + if (this.lang != null && !this.lang.isEmpty()) + row.child(IKey.lang(this.lang).asWidget().align(Alignment.CenterRight).height(18)); + + return row; + } + } } diff --git a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java index f6d3f4857f7..7fed3591548 100644 --- a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java @@ -6,7 +6,11 @@ import gregtech.api.gui.ingredient.IGhostIngredientTarget; import gregtech.api.gui.ingredient.IIngredientSlot; import gregtech.api.gui.resources.IGuiTexture; -import gregtech.api.util.*; +import gregtech.api.util.GTLog; +import gregtech.api.util.LocalizationUtils; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.TextFormattingUtil; import gregtech.client.utils.RenderUtil; import gregtech.client.utils.TooltipHelper; diff --git a/src/main/java/gregtech/api/items/metaitem/MetaItem.java b/src/main/java/gregtech/api/items/metaitem/MetaItem.java index f2674add426..a17559b05b2 100644 --- a/src/main/java/gregtech/api/items/metaitem/MetaItem.java +++ b/src/main/java/gregtech/api/items/metaitem/MetaItem.java @@ -33,6 +33,7 @@ import gregtech.api.util.Mods; import gregtech.client.utils.ToolChargeBarRenderer; import gregtech.common.ConfigHolder; +import gregtech.common.covers.filter.IFilter; import gregtech.common.creativetab.GTCreativeTabs; import net.minecraft.client.Minecraft; @@ -781,6 +782,7 @@ public MetaItem getMetaItem() { private final List behaviours = new ArrayList<>(); private IItemUseManager useManager; private ItemUIFactory uiManager; + private IFilter.Factory filterBehavior; private IItemColorProvider colorProvider; private IItemDurabilityManager durabilityManager; private IEnchantabilityHelper enchantabilityHelper; @@ -908,9 +910,12 @@ protected void addItemComponentsInternal(IItemComponent... stats) { if (itemComponent instanceof IFoodBehavior) { this.useManager = new FoodUseManager((IFoodBehavior) itemComponent); } - if (itemComponent instanceof ItemUIFactory) + if (itemComponent instanceof ItemUIFactory) { this.uiManager = (ItemUIFactory) itemComponent; - + } + if (itemComponent instanceof IFilter.Factory) { + this.filterBehavior = (IFilter.Factory) itemComponent; + } if (itemComponent instanceof IItemColorProvider) { this.colorProvider = (IItemColorProvider) itemComponent; } @@ -956,6 +961,11 @@ public ItemUIFactory getUIManager() { return uiManager; } + @Nullable + public IFilter.Factory getFilterFactory() { + return filterBehavior; + } + @Nullable public IItemColorProvider getColorProvider() { return colorProvider; diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 3c99abaee1e..d585285efc2 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -12,6 +12,7 @@ * while MUI port is still ongoing. When MUI port is done, this annotation will be removed. */ // TODO ^ +@SuppressWarnings("unused") @ApiStatus.Experimental public class GTGuiTextures { @@ -153,6 +154,56 @@ public static class IDs { .canApplyTheme() .build(); + public static final UITexture[] BUTTON_BLACKLIST = slice("textures/gui/widget/button_blacklist.png", + 16, 32, 16, 16, true); + public static final UITexture[] BUTTON_IGNORE_DAMAGE = slice("textures/gui/widget/button_filter_damage.png", + 16, 32, 16, 16, true); + public static final UITexture[] BUTTON_IGNORE_NBT = slice("textures/gui/widget/button_filter_nbt.png", + 16, 32, 16, 16, true); + + public static final UITexture[] BUTTON_CASE_SENSITIVE = slice( + "textures/gui/widget/ore_filter/button_case_sensitive.png", + 16, 32, 16, 16, true); + + public static final UITexture[] BUTTON_MATCH_ALL = slice("textures/gui/widget/ore_filter/button_match_all.png", + 16, 32, 16, 16, true); + + public static final UITexture OREDICT_ERROR = fullImage("textures/gui/widget/ore_filter/error.png"); + public static final UITexture OREDICT_INFO = fullImage("textures/gui/widget/ore_filter/info.png"); + public static final UITexture OREDICT_MATCH = fullImage("textures/gui/widget/ore_filter/match.png"); + public static final UITexture OREDICT_NO_MATCH = fullImage("textures/gui/widget/ore_filter/no_match.png"); + public static final UITexture OREDICT_SUCCESS = fullImage("textures/gui/widget/ore_filter/success.png"); + public static final UITexture OREDICT_WAITING = fullImage("textures/gui/widget/ore_filter/waiting.png"); + public static final UITexture OREDICT_WARN = fullImage("textures/gui/widget/ore_filter/warn.png"); + + public static final UITexture[] MANUAL_IO_OVERLAY = slice("textures/gui/overlay/manual_io_overlay.png", + 18, 18 * 3, 18, 18, true); + public static final UITexture[] CONVEYOR_MODE_OVERLAY = slice("textures/gui/overlay/conveyor_mode_overlay.png", + 18, 18 * 2, 18, 18, true); + + public static final UITexture[] TRANSFER_MODE_OVERLAY = slice("textures/gui/overlay/transfer_mode_overlay.png", + 18, 18 * 3, 18, 18, true); + + public static final UITexture[] FLUID_TRANSFER_MODE_OVERLAY = slice( + "textures/gui/overlay/fluid_transfer_mode_overlay.png", + 18, 18 * 3, 18, 18, true); + + public static final UITexture[] DISTRIBUTION_MODE_OVERLAY = slice( + "textures/gui/widget/button_distribution_mode.png", + 16, 48, 16, 16, true); + + public static final UITexture[] VOIDING_MODE_OVERLAY = slice( + "textures/gui/overlay/voiding_mode_overlay.png", + 16, 32, 16, 16, true); + + public static final UITexture[] FILTER_MODE_OVERLAY = slice( + "textures/gui/overlay/filter_mode_overlay.png", + 16, 48, 16, 16, true); + + public static final UITexture[] PRIVATE_MODE_BUTTON = slice( + "textures/gui/widget/button_public_private.png", + 18, 36, 18, 18, true); + // todo bronze/steel/primitive fluid slots? // SLOT OVERLAYS @@ -205,6 +256,9 @@ public static class IDs { public static final UITexture EXTRACTOR_OVERLAY_STEEL = fullImage( "textures/gui/overlay/extractor_overlay_steel.png"); public static final UITexture FILTER_SLOT_OVERLAY = fullImage("textures/gui/overlay/filter_slot_overlay.png", true); + public static final UITexture FILTER_SETTINGS_OVERLAY = fullImage( + "textures/gui/overlay/filter_settings_overlay.png", + true); public static final UITexture FURNACE_OVERLAY_1 = fullImage("textures/gui/overlay/furnace_overlay_1.png", true); public static final UITexture FURNACE_OVERLAY_2 = fullImage("textures/gui/overlay/furnace_overlay_2.png", true); public static final UITexture FURNACE_OVERLAY_BRONZE = fullImage("textures/gui/overlay/furnace_overlay_bronze.png"); @@ -265,7 +319,7 @@ public static class IDs { public static final UITexture BUTTON = new UITexture.Builder() .location(GTValues.MODID, "textures/gui/widget/button.png") .imageSize(18, 18) - .adaptable(1) + .adaptable(2) .name(IDs.STANDARD_BUTTON) .canApplyTheme() .build(); @@ -274,13 +328,13 @@ public static class IDs { .location("modularui", "gui/widgets/mc_button.png") // todo .imageSize(16, 32) .uv(0.0f, 0.0f, 1.0f, 0.5f) - .adaptable(1) + .adaptable(2) .build(); public static final UITexture MC_BUTTON_DISABLED = new UITexture.Builder() .location("modularui", "gui/widgets/mc_button_disabled.png") // todo .imageSize(16, 16) - .adaptable(1) + .adaptable(2) .build(); // BUTTON OVERLAYS @@ -453,6 +507,29 @@ private static UITexture fullImage(String path, boolean canApplyTheme) { return UITexture.fullImage(GTValues.MODID, path, canApplyTheme); } + @SuppressWarnings("SameParameterValue") + private static UITexture[] slice(String path, int imageWidth, int imageHeight, int sliceWidth, int sliceHeight, + boolean canApplyTheme) { + if (imageWidth % sliceWidth != 0 || imageHeight % sliceHeight != 0) + throw new IllegalArgumentException("Slice height and slice width must divide the image evenly!"); + + int countX = imageWidth / sliceWidth; + int countY = imageHeight / sliceHeight; + UITexture[] slices = new UITexture[countX * countY]; + + for (int indexX = 0; indexX < countX; indexX++) { + for (int indexY = 0; indexY < countY; indexY++) { + slices[(indexX * countX) + indexY] = UITexture.builder() + .location(GTValues.MODID, path) + .canApplyTheme(canApplyTheme) + .imageSize(imageWidth, imageHeight) + .uv(indexX * sliceWidth, indexY * sliceHeight, sliceWidth, sliceHeight) + .build(); + } + } + return slices; + } + private static UITexture progressBar(String path) { return progressBar(path, 20, 40, false); } diff --git a/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java b/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java new file mode 100644 index 00000000000..bf3c6c581d7 --- /dev/null +++ b/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java @@ -0,0 +1,150 @@ +package gregtech.api.mui.sync; + +import gregtech.common.covers.filter.readers.SimpleFluidFilterReader; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; + +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.FluidSlotSyncHandler; +import org.jetbrains.annotations.Nullable; + +public class FixedFluidSlotSH extends FluidSlotSyncHandler { + + @Nullable + private FluidStack lastStoredPhantomFluid; + + public FixedFluidSlotSH(IFluidTank fluidTank) { + super(fluidTank); + if (this.updateCacheFromSource(true) && fluidTank.getFluid() != null) { + this.lastStoredPhantomFluid = fluidTank.getFluid().copy(); + } + } + + @Override + public void readOnServer(int id, PacketBuffer buf) { + super.readOnServer(id, buf); + if (id == 0) { + var fluid = getFluidTank().getFluid(); + if (this.lastStoredPhantomFluid == null && fluid != null || + (this.lastStoredPhantomFluid != null && !this.lastStoredPhantomFluid.isFluidEqual(fluid))) { + this.lastStoredPhantomFluid = fluid; + } + } + } + + @Override + public void setValue(@Nullable FluidStack value, boolean setSource, boolean sync) { + super.setValue(value, setSource, sync); + if (setSource) { + this.getFluidTank().drain(Integer.MAX_VALUE, true); + if (!isFluidEmpty(value)) { + this.getFluidTank().fill(value.copy(), true); + } + } + } + + @Override + public void tryClickPhantom(MouseData mouseData) { + EntityPlayer player = getSyncManager().getPlayer(); + ItemStack currentStack = player.inventory.getItemStack(); + FluidStack currentFluid = this.getFluidTank().getFluid(); + IFluidHandlerItem fluidHandlerItem = currentStack + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); + + if (mouseData.mouseButton == 0) { + if (currentStack.isEmpty() || fluidHandlerItem == null) { + if (this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + } else { + FluidStack cellFluid = fluidHandlerItem.drain(Integer.MAX_VALUE, false); + if ((this.controlsAmount() || currentFluid == null) && cellFluid != null) { + if (this.canFillSlot()) { + if (!this.controlsAmount()) { + cellFluid.amount = 1; + } + if (this.getFluidTank().fill(cellFluid, true) > 0) { + this.lastStoredPhantomFluid = cellFluid.copy(); + } + } + } else { + if (this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + } + } + } else if (mouseData.mouseButton == 1) { + if (this.canFillSlot()) { + if (currentFluid != null) { + if (this.controlsAmount()) { + FluidStack toFill = currentFluid.copy(); + toFill.amount = 1000; + this.getFluidTank().fill(toFill, true); + } + } else if (this.lastStoredPhantomFluid != null) { + FluidStack toFill = this.lastStoredPhantomFluid.copy(); + toFill.amount = this.controlsAmount() ? 1 : toFill.amount; + this.getFluidTank().fill(toFill, true); + } + } + } else if (mouseData.mouseButton == 2 && currentFluid != null && this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + } + + @Override + public void tryScrollPhantom(MouseData mouseData) { + FluidStack currentFluid = this.getFluidTank().getFluid(); + int amount = mouseData.mouseButton; + if (!this.controlsAmount()) { + var fluid = getFluidTank().getFluid(); + int newAmt = amount == 1 ? 1 : 0; + if (fluid != null && fluid.amount != newAmt) { + fluid.amount = newAmt; + setValue(fluid, true, true); + return; + } + } + if (mouseData.shift) { + amount *= 10; + } + if (mouseData.ctrl) { + amount *= 100; + } + if (mouseData.alt) { + amount *= 1000; + } + if (currentFluid == null) { + if (amount > 0 && this.lastStoredPhantomFluid != null) { + FluidStack toFill = this.lastStoredPhantomFluid.copy(); + toFill.amount = this.controlsAmount() ? amount : 1; + this.getFluidTank().fill(toFill, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + return; + } + if (amount > 0) { + FluidStack toFill = currentFluid.copy(); + toFill.amount = amount; + this.getFluidTank().fill(toFill, true); + } else if (amount < 0) { + this.getFluidTank().drain(-amount, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + } + + @Override + public boolean controlsAmount() { + if (getFluidTank() instanceof SimpleFluidFilterReader.WritableFluidTank writableFluidTank) { + return writableFluidTank.showAmount(); + } + return super.controlsAmount(); + } +} diff --git a/src/main/java/gregtech/common/covers/CoverBehaviors.java b/src/main/java/gregtech/common/covers/CoverBehaviors.java index 3e5779fb3bf..78413327163 100644 --- a/src/main/java/gregtech/common/covers/CoverBehaviors.java +++ b/src/main/java/gregtech/common/covers/CoverBehaviors.java @@ -8,10 +8,6 @@ import gregtech.api.util.GTLog; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.detector.*; -import gregtech.common.covers.filter.OreDictionaryItemFilter; -import gregtech.common.covers.filter.SimpleFluidFilter; -import gregtech.common.covers.filter.SimpleItemFilter; -import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.CoverDigitalInterfaceWirelessPlaceBehaviour; @@ -67,12 +63,12 @@ public static void init() { registerBehavior(gregtechId("ore_dictionary_filter"), MetaItems.ORE_DICTIONARY_FILTER, (def, tile, side) -> new CoverItemFilter(def, tile, side, "cover.ore_dictionary_filter.title", - Textures.ORE_DICTIONARY_FILTER_OVERLAY, new OreDictionaryItemFilter())); + Textures.ORE_DICTIONARY_FILTER_OVERLAY)); registerBehavior(gregtechId("item_filter"), MetaItems.ITEM_FILTER, (def, tile, side) -> new CoverItemFilter(def, - tile, side, "cover.item_filter.title", Textures.ITEM_FILTER_FILTER_OVERLAY, new SimpleItemFilter())); + tile, side, "cover.item_filter.title", Textures.ITEM_FILTER_FILTER_OVERLAY)); registerBehavior(gregtechId("fluid_filter"), MetaItems.FLUID_FILTER, (def, tile, side) -> new CoverFluidFilter(def, tile, side, "cover.fluid_filter.title", - Textures.FLUID_FILTER_OVERLAY, new SimpleFluidFilter())); + Textures.FLUID_FILTER_OVERLAY)); registerBehavior(gregtechId("shutter"), MetaItems.COVER_SHUTTER, CoverShutter::new); registerBehavior(gregtechId("solar_panel.basic"), MetaItems.COVER_SOLAR_PANEL, @@ -100,7 +96,7 @@ public static void init() { CoverMachineController::new); registerBehavior(gregtechId("smart_filter"), MetaItems.SMART_FILTER, (def, tile, side) -> new CoverItemFilter(def, tile, side, "cover.smart_item_filter.title", - Textures.SMART_FILTER_FILTER_OVERLAY, new SmartItemFilter())); + Textures.SMART_FILTER_FILTER_OVERLAY)); registerBehavior(gregtechId("facade"), MetaItems.COVER_FACADE, CoverFacade::new); registerBehavior(gregtechId("screen"), MetaItems.COVER_SCREEN, CoverScreen::new); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 1408ae77c56..127c852fb83 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -1,6 +1,5 @@ package gregtech.common.covers; -import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; @@ -9,9 +8,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; import gregtech.client.renderer.texture.Textures; @@ -26,7 +24,12 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.*; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.ITickable; import net.minecraft.util.math.MathHelper; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; @@ -39,10 +42,24 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import org.jetbrains.annotations.NotNull; @@ -76,7 +93,7 @@ public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView } public void setTransferRate(int transferRate) { - this.transferRate = transferRate; + this.transferRate = MathHelper.clamp(transferRate, 1, maxItemTransferRate); CoverableView coverable = getCoverableView(); coverable.markDirty(); @@ -168,7 +185,7 @@ protected int doTransferItemsAny(IItemHandler itemHandler, IItemHandler myItemHa } protected int doTransferItemsByGroup(IItemHandler itemHandler, IItemHandler myItemHandler, - Map itemInfos, int maxTransferAmount) { + Map itemInfos, int maxTransferAmount) { if (conveyorMode == ConveyorMode.IMPORT) { return moveInventoryItems(itemHandler, myItemHandler, itemInfos, maxTransferAmount); } else if (conveyorMode == ConveyorMode.EXPORT) { @@ -177,8 +194,8 @@ protected int doTransferItemsByGroup(IItemHandler itemHandler, IItemHandler myIt return 0; } - protected Map doCountDestinationInventoryItemsByMatchIndex(IItemHandler itemHandler, - IItemHandler myItemHandler) { + protected Map doCountDestinationInventoryItemsByMatchIndex(IItemHandler itemHandler, + IItemHandler myItemHandler) { if (conveyorMode == ConveyorMode.IMPORT) { return countInventoryItemsByMatchSlot(myItemHandler); } else if (conveyorMode == ConveyorMode.EXPORT) { @@ -265,15 +282,17 @@ protected static boolean moveInventoryItemsExact(IItemHandler sourceInventory, I } protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targetInventory, - Map itemInfos, int maxTransferAmount) { + Map itemInfos, int maxTransferAmount) { int itemsLeftToTransfer = maxTransferAmount; for (int i = 0; i < sourceInventory.getSlots(); i++) { ItemStack itemStack = sourceInventory.getStackInSlot(i); if (itemStack.isEmpty()) { continue; } - Object matchSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (matchSlotIndex == null || !itemInfos.containsKey(matchSlotIndex)) { + + var matchResult = itemFilterContainer.match(itemStack); + int matchSlotIndex = matchResult.getFilterIndex(); + if (!matchResult.isMatched() || !itemInfos.containsKey(matchSlotIndex)) { continue; } @@ -317,9 +336,10 @@ protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targ if (sourceStack.isEmpty()) { continue; } - if (!itemFilterContainer.testItemStack(sourceStack)) { - continue; - } + + var result = itemFilterContainer.match(sourceStack); + if (!result.isMatched()) continue; + ItemStack remainder = GTTransferUtils.insertItem(targetInventory, sourceStack, true); int amountToInsert = sourceStack.getCount() - remainder.getCount(); @@ -341,11 +361,11 @@ protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targ protected static class TypeItemInfo { public final ItemStack itemStack; - public final Object filterSlot; + public final int filterSlot; public final IntList slots; public int totalCount; - public TypeItemInfo(ItemStack itemStack, Object filterSlot, IntList slots, int totalCount) { + public TypeItemInfo(ItemStack itemStack, int filterSlot, IntList slots, int totalCount) { this.itemStack = itemStack; this.filterSlot = filterSlot; this.slots = slots; @@ -355,11 +375,11 @@ public TypeItemInfo(ItemStack itemStack, Object filterSlot, IntList slots, int t protected static class GroupItemInfo { - public final Object filterSlot; + public final int filterSlot; public final Set itemStackTypes; public int totalCount; - public GroupItemInfo(Object filterSlot, Set itemStackTypes, int totalCount) { + public GroupItemInfo(int filterSlot, Set itemStackTypes, int totalCount) { this.filterSlot = filterSlot; this.itemStackTypes = itemStackTypes; this.totalCount = totalCount; @@ -375,12 +395,13 @@ protected Map countInventoryItemsByType(@NotNull IItemH if (itemStack.isEmpty()) { continue; } - Object transferSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (transferSlotIndex == null) { - continue; - } + + var matchResult = itemFilterContainer.match(itemStack); + if (!matchResult.isMatched()) continue; + if (!result.containsKey(itemStack)) { - TypeItemInfo itemInfo = new TypeItemInfo(itemStack.copy(), transferSlotIndex, new IntArrayList(), 0); + TypeItemInfo itemInfo = new TypeItemInfo(itemStack.copy(), matchResult.getFilterIndex(), + new IntArrayList(), 0); itemInfo.totalCount += itemStack.getCount(); itemInfo.slots.add(srcIndex); result.put(itemStack.copy(), itemInfo); @@ -394,28 +415,30 @@ protected Map countInventoryItemsByType(@NotNull IItemH } @NotNull - protected Map countInventoryItemsByMatchSlot(@NotNull IItemHandler inventory) { - Map result = new Object2ObjectOpenHashMap<>(); + protected Map countInventoryItemsByMatchSlot(@NotNull IItemHandler inventory) { + Map result = new Int2ObjectOpenHashMap<>(); for (int srcIndex = 0; srcIndex < inventory.getSlots(); srcIndex++) { ItemStack itemStack = inventory.getStackInSlot(srcIndex); if (itemStack.isEmpty()) { continue; } - Object transferSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (transferSlotIndex == null) { - continue; - } - if (!result.containsKey(transferSlotIndex)) { - GroupItemInfo itemInfo = new GroupItemInfo(transferSlotIndex, + + var matchResult = itemFilterContainer.match(itemStack); + if (!matchResult.isMatched()) continue; + int matchedSlot = matchResult.getFilterIndex(); + + if (!result.containsKey(matchedSlot)) { + GroupItemInfo itemInfo = new GroupItemInfo(matchedSlot, new ObjectOpenCustomHashSet<>(ItemStackHashStrategy.comparingAllButCount()), 0); itemInfo.itemStackTypes.add(itemStack.copy()); itemInfo.totalCount += itemStack.getCount(); - result.put(transferSlotIndex, itemInfo); + result.put(matchedSlot, itemInfo); } else { - GroupItemInfo itemInfo = result.get(transferSlotIndex); + GroupItemInfo itemInfo = result.get(matchedSlot); itemInfo.itemStackTypes.add(itemStack.copy()); itemInfo.totalCount += itemStack.getCount(); } + } return result; } @@ -432,7 +455,7 @@ public boolean canInteractWithOutputSide() { @Override public void onRemoval() { - dropInventoryContents(itemFilterContainer.getFilterInventory()); + dropInventoryContents(itemFilterContainer); } @Override @@ -473,57 +496,123 @@ public T getCapability(Capability capability, T defaultValue) { return defaultValue; } - protected String getUITitle() { - return "cover.conveyor.title"; + @Override + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192 + 18); + + getItemFilterContainer().setMaxTransferSize(getMaxStackSize()); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createUI(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var column = new Column().top(24).margin(7, 0) + .widthRel(1f).coverChildrenHeight(); + + EnumSyncValue manualIOmode = new EnumSyncValue<>(ManualImportExportMode.class, + this::getManualImportExportMode, this::setManualImportExportMode); + + EnumSyncValue conveyorMode = new EnumSyncValue<>(ConveyorMode.class, + this::getConveyorMode, this::setConveyorMode); + + IntSyncValue throughput = new IntSyncValue(this::getTransferRate, this::setTransferRate); + throughput.updateCacheFromSource(true); + + StringSyncValue formattedThroughput = new StringSyncValue(throughput::getStringValue, + throughput::setStringValue); + + EnumSyncValue distributionMode = new EnumSyncValue<>(DistributionMode.class, + this::getDistributionMode, this::setDistributionMode); + + guiSyncManager.syncValue("manual_io", manualIOmode); + guiSyncManager.syncValue("conveyor_mode", conveyorMode); + guiSyncManager.syncValue("distribution_mode", distributionMode); + guiSyncManager.syncValue("throughput", throughput); + + if (createThroughputRow()) + column.child(new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ButtonWidget<>() + .left(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() - getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(false)))) + .child(new TextFieldWidget() + .left(18).right(18) + .setTextColor(Color.WHITE.darker(1)) + .setNumbers(1, maxItemTransferRate) + .value(formattedThroughput) + .background(GTGuiTextures.DISPLAY)) + .child(new ButtonWidget<>() + .right(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() + getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(true))))); + + if (createFilterRow()) + column.child(getItemFilterContainer().initUI(mainPanel, guiSyncManager)); + + if (createManualIOModeRow()) + column.child(new EnumRowBuilder<>(ManualImportExportMode.class) + .value(manualIOmode) + .lang("cover.generic.manual_io") + .overlay(GTGuiTextures.MANUAL_IO_OVERLAY) + .build()); + + if (createConveyorModeRow()) + column.child(new EnumRowBuilder<>(ConveyorMode.class) + .value(conveyorMode) + .lang("cover.generic.io") + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) + .build()); + + if (createDistributionModeRow()) + column.child(new EnumRowBuilder<>(DistributionMode.class) + .value(distributionMode) + .overlay(16, GTGuiTextures.DISTRIBUTION_MODE_OVERLAY) + .lang("cover.conveyor.distribution.name") + .build()); + + return column; + } + + protected boolean createThroughputRow() { + return true; } - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - return builder.build(this, player); + protected boolean createFilterRow() { + return true; } - @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle(), GTValues.VN[tier])); - - primaryGroup.addWidget(new IncrementButtonWidget(136, 20, 30, 20, 1, 8, 64, 512, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - primaryGroup.addWidget(new IncrementButtonWidget(10, 20, 30, 20, -1, -8, -64, -512, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - - primaryGroup.addWidget(new ImageWidget(40, 20, 96, 20, GuiTextures.DISPLAY)); - primaryGroup.addWidget(new TextFieldWidget2(42, 26, 92, 20, () -> String.valueOf(transferRate), val -> { - if (val != null && !val.isEmpty()) - setTransferRate(MathHelper.clamp(Integer.parseInt(val), 1, maxItemTransferRate)); - }) - .setNumbersOnly(1, maxItemTransferRate) - .setMaxLength(4) - .setPostFix("cover.conveyor.transfer_rate")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 45, 75, 20, - ConveyorMode.class, this::getConveyorMode, this::setConveyorMode)); - primaryGroup.addWidget(new CycleButtonWidget(7, 166, 116, 20, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - if (getTileEntityHere() instanceof TileEntityItemPipe || - getNeighbor(getAttachedSide()) instanceof TileEntityItemPipe) { - final ImageCycleButtonWidget distributionModeButton = new ImageCycleButtonWidget(149, 166, 20, 20, - GuiTextures.DISTRIBUTION_MODE, 3, - () -> distributionMode.ordinal(), - val -> setDistributionMode(DistributionMode.values()[val])) - .setTooltipHoverString(val -> DistributionMode.values()[val].getName()); - primaryGroup.addWidget(distributionModeButton); - } + protected boolean createManualIOModeRow() { + return true; + } - this.itemFilterContainer.initUI(70, primaryGroup::addWidget); + protected boolean createConveyorModeRow() { + return true; + } + + protected boolean createDistributionModeRow() { + return true; + } - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 190 + 82) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 190); - return buildUI(builder, player); + protected int getMaxStackSize() { + return 1; } @Override @@ -546,17 +635,23 @@ public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { } @Override - public void writeInitialSyncData(PacketBuffer packetBuffer) { + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.writeInitialSyncData(packetBuffer); - packetBuffer.writeEnumValue(conveyorMode); - packetBuffer.writeEnumValue(distributionMode); + packetBuffer.writeInt(transferRate); + packetBuffer.writeByte(conveyorMode.ordinal()); + packetBuffer.writeByte(distributionMode.ordinal()); + packetBuffer.writeByte(manualImportExportMode.ordinal()); + getItemFilterContainer().writeInitialSyncData(packetBuffer); } @Override public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); - this.conveyorMode = packetBuffer.readEnumValue(ConveyorMode.class); - this.distributionMode = packetBuffer.readEnumValue(DistributionMode.class); + this.transferRate = packetBuffer.readInt(); + this.conveyorMode = ConveyorMode.VALUES[packetBuffer.readByte()]; + this.distributionMode = DistributionMode.VALUES[packetBuffer.readByte()]; + this.manualImportExportMode = ManualImportExportMode.VALUES[packetBuffer.readByte()]; + getItemFilterContainer().readInitialSyncData(packetBuffer); } @Override @@ -574,11 +669,12 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); - this.conveyorMode = ConveyorMode.values()[tagCompound.getInteger("ConveyorMode")]; - this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.conveyorMode = ConveyorMode.VALUES[tagCompound.getInteger("ConveyorMode")]; + this.distributionMode = DistributionMode.VALUES[tagCompound.getInteger("DistributionMode")]; this.isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); - this.manualImportExportMode = ManualImportExportMode.values()[tagCompound.getInteger("ManualImportExportMode")]; + this.manualImportExportMode = ManualImportExportMode.VALUES[tagCompound.getInteger("ManualImportExportMode")]; this.itemFilterContainer.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.itemFilterContainer.handleLegacyNBT(tagCompound.getCompoundTag("Filter")); } @Override @@ -592,6 +688,7 @@ public enum ConveyorMode implements IStringSerializable, IIOMode { IMPORT("cover.conveyor.mode.import"), EXPORT("cover.conveyor.mode.export"); + public static final ConveyorMode[] VALUES = values(); public final String localeName; ConveyorMode(String localeName) { @@ -623,7 +720,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate return stack; } if (manualImportExportMode == ManualImportExportMode.FILTERED && - !itemFilterContainer.testItemStack(stack)) { + !itemFilterContainer.test(stack)) { return stack; } return super.insertItem(slot, stack, simulate); @@ -637,7 +734,7 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) { } if (manualImportExportMode == ManualImportExportMode.FILTERED) { ItemStack result = super.extractItem(slot, amount, true); - if (result.isEmpty() || !itemFilterContainer.testItemStack(result)) { + if (result.isEmpty() || !itemFilterContainer.test(result)) { return ItemStack.EMPTY; } return simulate ? result : super.extractItem(slot, amount, false); diff --git a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java index b34348c69bb..ffe2f9ed8a0 100644 --- a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java +++ b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java @@ -6,9 +6,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.FluidTankSwitchShim; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.VirtualTankRegistry; @@ -20,7 +19,11 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; -import net.minecraft.util.*; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ITickable; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -30,6 +33,22 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.FluidSlotSyncHandler; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.FluidSlot; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -106,7 +125,7 @@ public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFaci @Override public void onRemoval() { - dropInventoryContents(fluidFilter.getFilterInventory()); + dropInventoryContents(fluidFilter); } @Override @@ -121,9 +140,9 @@ protected void transferFluids() { getAttachedSide()); if (fluidHandler == null) return; if (pumpMode == CoverPump.PumpMode.IMPORT) { - GTTransferUtils.transferFluids(fluidHandler, linkedTank, TRANSFER_RATE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(fluidHandler, linkedTank, TRANSFER_RATE, fluidFilter::test); } else if (pumpMode == CoverPump.PumpMode.EXPORT) { - GTTransferUtils.transferFluids(linkedTank, fluidHandler, TRANSFER_RATE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(linkedTank, fluidHandler, TRANSFER_RATE, fluidFilter::test); } } @@ -143,36 +162,86 @@ public void openUI(EntityPlayerMP player) { } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup widgetGroup = new WidgetGroup(); - widgetGroup.addWidget(new LabelWidget(10, 5, "cover.ender_fluid_link.title")); - widgetGroup.addWidget(new ToggleButtonWidget(12, 18, 18, 18, GuiTextures.BUTTON_PUBLIC_PRIVATE, - this::isPrivate, this::setPrivate) - .setTooltipText("cover.ender_fluid_link.private.tooltip")); - widgetGroup.addWidget(new SyncableColorRectWidget(35, 18, 18, 18, () -> color) - .setBorderWidth(1) - .drawCheckerboard(4, 4)); - widgetGroup.addWidget(new TextFieldWidget(58, 13, 58, 18, true, - this::getColorStr, this::updateColor, 8) - .setValidator(str -> COLOR_INPUT_PATTERN.matcher(str).matches())); - widgetGroup.addWidget(new TankWidget(this.linkedTank, 123, 18, 18, 18) - .setContainerClicking(true, true) - .setBackgroundTexture(GuiTextures.FLUID_SLOT).setAlwaysShowFull(true)); - widgetGroup.addWidget(new ImageWidget(147, 19, 16, 16) - .setImage(GuiTextures.INFO_ICON) - .setPredicate(() -> isColorTemp) - .setTooltip("cover.ender_fluid_link.incomplete_hex") - .setIgnoreColor(true)); - widgetGroup.addWidget(new CycleButtonWidget(10, 42, 75, 18, - CoverPump.PumpMode.class, this::getPumpMode, this::setPumpMode)); - widgetGroup.addWidget(new CycleButtonWidget(92, 42, 75, 18, - this::isIoEnabled, this::setIoEnabled, "cover.ender_fluid_link.iomode.disabled", - "cover.ender_fluid_link.iomode.enabled")); - this.fluidFilter.initUI(65, widgetGroup::addWidget); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 221) - .widget(widgetGroup) - .bindPlayerInventory(player.inventory, 139) - .build(this, player); + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192); + + getFluidFilterContainer().setMaxTransferSize(1); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createWidgets(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected Column createWidgets(ModularPanel panel, GuiSyncManager syncManager) { + var isPrivate = new BooleanSyncValue(this::isPrivate, this::setPrivate); + isPrivate.updateCacheFromSource(true); + + var color = new StringSyncValue(this::getColorStr, this::updateColor); + color.updateCacheFromSource(true); + + var pumpMode = new EnumSyncValue<>(CoverPump.PumpMode.class, this::getPumpMode, this::setPumpMode); + syncManager.syncValue("pump_mode", pumpMode); + pumpMode.updateCacheFromSource(true); + + var ioEnabled = new BooleanSyncValue(this::isIOEnabled, this::setIoEnabled); + + var fluidTank = new FluidSlotSyncHandler(this.linkedTank); + fluidTank.updateCacheFromSource(true); + + return new Column().coverChildrenHeight().top(24) + .margin(7, 0).widthRel(1f) + .child(new Row().marginBottom(2) + .coverChildrenHeight() + .child(new ToggleButton() + .tooltip(tooltip -> tooltip.setAutoUpdate(true)) + .background(GTGuiTextures.PRIVATE_MODE_BUTTON[0]) + .hoverBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[0]) + .selectedBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[1]) + .selectedHoverBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[1]) + .tooltipBuilder(tooltip -> tooltip.addLine(IKey.lang(this.isPrivate ? + "cover.ender_fluid_link.private.tooltip.enabled" : + "cover.ender_fluid_link.private.tooltip.disabled"))) + .marginRight(2) + .value(isPrivate)) + .child(new DynamicDrawable(() -> new Rectangle() + .setColor(this.color) + .asIcon().size(16)) + .asWidget() + .background(GTGuiTextures.SLOT) + .size(18).marginRight(2)) + .child(new TextFieldWidget().height(18) + .value(color) + .setValidator(s -> { + if (s.length() != 8) { + return color.getStringValue(); + } + return s; + }) + .setPattern(COLOR_INPUT_PATTERN) + .widthRel(0.5f).marginRight(2)) + .child(new FluidSlot().size(18) + .syncHandler(fluidTank))) + .child(new Row().marginBottom(2) + .coverChildrenHeight() + .child(new ToggleButton() + .value(ioEnabled) + .overlay(IKey.dynamic(() -> IKey.lang(this.ioEnabled ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))) + .child(getFluidFilterContainer().initUI(panel, syncManager)) + .child(new EnumRowBuilder<>(CoverPump.PumpMode.class) + .value(pumpMode) + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) + .lang("cover.pump.mode") + .build()); } public void updateColor(String str) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index cd5d06ee5a4..648968c90dc 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -5,19 +5,19 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; -import gregtech.common.covers.filter.FluidFilter; -import gregtech.common.covers.filter.FluidFilterWrapper; +import gregtech.client.utils.TooltipHelper; +import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.FluidFilterContainer; 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.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -32,26 +32,34 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; + public class CoverFluidFilter extends CoverBase implements CoverWithUI { protected final String titleLocale; protected final SimpleOverlayRenderer texture; - protected final FluidFilterWrapper fluidFilter; + protected final FluidFilterContainer fluidFilterContainer; protected FluidFilterMode filterMode; protected FluidHandlerFiltered fluidHandler; public CoverFluidFilter(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, - @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture, - FluidFilter fluidFilter) { + @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture) { super(definition, coverableView, attachedSide); + this.fluidFilterContainer = new FluidFilterContainer(this); this.filterMode = FluidFilterMode.FILTER_FILL; this.titleLocale = titleLocale; this.texture = texture; - this.fluidFilter = new FluidFilterWrapper(this); - this.fluidFilter.setFluidFilter(fluidFilter); } public void setFilterMode(FluidFilterMode filterMode) { @@ -59,16 +67,51 @@ public void setFilterMode(FluidFilterMode filterMode) { this.getCoverableView().markDirty(); } - public FluidFilterMode getFilterMode() { - return filterMode; + @Override + public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFacing side, + @Nullable EntityPlayer player, @NotNull ItemStack itemStack) { + super.onAttachment(coverableView, side, player, itemStack); + var dropStack = GTUtility.copy(1, itemStack); + this.fluidFilterContainer.setFilterStack(dropStack); } - public FluidFilterWrapper getFluidFilter() { - return this.fluidFilter; + @Override + public @NotNull ItemStack getPickItem() { + if (TooltipHelper.isCtrlDown()) + return getCoverableView().getStackForm(); + + return this.fluidFilterContainer.getFilterStack(); } - public boolean testFluidStack(FluidStack stack) { - return fluidFilter.testFluidStack(stack); + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + packetBuffer.writeByte(this.filterMode.ordinal()); + packetBuffer.writeBoolean(this.fluidFilterContainer.hasFilter()); + if (this.fluidFilterContainer.hasFilter()) { + packetBuffer.writeItemStack(this.fluidFilterContainer.getFilterStack()); + } + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + this.filterMode = FluidFilterMode.VALUES[packetBuffer.readByte()]; + if (!packetBuffer.readBoolean()) return; + try { + this.fluidFilterContainer.setFilterStack(packetBuffer.readItemStack()); + } catch (IOException e) { + GTLog.logger.error("Failed to read filter for CoverFluidFilter! %s", getPos().toString()); + } + } + + public FluidFilterMode getFilterMode() { + return filterMode; + } + + @SuppressWarnings("DataFlowIssue") // this cover always has a filter + public @NotNull BaseFilter getFilter() { + return this.fluidFilterContainer.hasFilter() ? + this.fluidFilterContainer.getFilter() : + BaseFilter.ERROR_FILTER; } @Override @@ -89,18 +132,32 @@ public boolean canPipePassThrough() { return EnumActionResult.SUCCESS; } - public ModularUI createUI(EntityPlayer player) { - WidgetGroup fluidFilterGroup = new WidgetGroup(); - fluidFilterGroup.addWidget(new LabelWidget(10, 5, "cover.fluid_filter.title")); - fluidFilterGroup.addWidget(new CycleButtonWidget(10, 20, 110, 20, - GTUtility.mapToString(FluidFilterMode.values(), (it) -> it.localeName), () -> this.filterMode.ordinal(), - (newMode) -> this.setFilterMode(FluidFilterMode.values()[newMode]))); - this.fluidFilter.initUI(45, fluidFilterGroup::addWidget); - this.fluidFilter.blacklistUI(45, fluidFilterGroup::addWidget, () -> true); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 105 + 82) - .widget(fluidFilterGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 105) - .build(this, player); + @Override + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var filteringMode = new EnumSyncValue<>(FluidFilterMode.class, this::getFilterMode, this::setFilterMode); + + guiSyncManager.syncValue("filtering_mode", filteringMode); + this.fluidFilterContainer.setMaxTransferSize(1); + getFilter().getFilterReader().readStack(this.fluidFilterContainer.getFilterStack()); + + return getFilter().createPanel(guiSyncManager) + .size(176, 194).padding(7) + .child(CoverWithUI.createTitleRow(getPickItem())) + .child(new Column().widthRel(1f).align(Alignment.TopLeft).top(22).coverChildrenHeight() + .child(new EnumRowBuilder<>(FluidFilterMode.class) + .value(filteringMode) + .lang("cover.filter.mode.title") + .overlay(16, GTGuiTextures.FILTER_MODE_OVERLAY) + .build()) + .child(new Rectangle().setColor(UI_TEXT_COLOR).asWidget() + .height(1).widthRel(0.95f).margin(0, 4)) + .child(getFilter().createWidgets(guiSyncManager))) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); } @Override @@ -127,18 +184,21 @@ public T getCapability(@NotNull Capability capability, @Nullable T defaul public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("FilterMode", this.filterMode.ordinal()); - tagCompound.setBoolean("IsBlacklist", this.fluidFilter.isBlacklistFilter()); - NBTTagCompound filterComponent = new NBTTagCompound(); - this.fluidFilter.getFluidFilter().writeToNBT(filterComponent); - tagCompound.setTag("Filter", filterComponent); + tagCompound.setTag("Filter", this.fluidFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = FluidFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - this.fluidFilter.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); + var filterTag = tagCompound.getCompoundTag("Filter"); + if (!filterTag.hasKey("FilterInventory")) { + this.fluidFilterContainer.setFilterStack(getDefinition().getDropItemStack()); + } else { + this.fluidFilterContainer.deserializeNBT(filterTag); + } + + this.fluidFilterContainer.handleLegacyNBT(tagCompound); } private class FluidHandlerFiltered extends FluidHandlerDelegate { @@ -148,7 +208,7 @@ public FluidHandlerFiltered(@NotNull IFluidHandler delegate) { } public int fill(FluidStack resource, boolean doFill) { - if (getFilterMode() == FluidFilterMode.FILTER_DRAIN || !fluidFilter.testFluidStack(resource)) { + if (getFilterMode() == FluidFilterMode.FILTER_DRAIN || !fluidFilterContainer.test(resource)) { return 0; } return super.fill(resource, doFill); @@ -156,7 +216,7 @@ public int fill(FluidStack resource, boolean doFill) { @Nullable public FluidStack drain(FluidStack resource, boolean doDrain) { - if (getFilterMode() == FluidFilterMode.FILTER_FILL || !fluidFilter.testFluidStack(resource)) { + if (getFilterMode() == FluidFilterMode.FILTER_FILL || !fluidFilterContainer.test(resource)) { return null; } return super.drain(resource, doDrain); @@ -166,7 +226,7 @@ public FluidStack drain(FluidStack resource, boolean doDrain) { public FluidStack drain(int maxDrain, boolean doDrain) { if (getFilterMode() != FluidFilterMode.FILTER_FILL) { FluidStack result = super.drain(maxDrain, false); - if (result == null || result.amount <= 0 || !fluidFilter.testFluidStack(result)) { + if (result == null || result.amount <= 0 || !fluidFilterContainer.test(result)) { return null; } return doDrain ? super.drain(maxDrain, true) : result; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 553f2734b46..dc55702148d 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -2,38 +2,37 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; -import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; -import gregtech.common.covers.filter.FluidFilter; import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.covers.filter.SimpleFluidFilter; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.event.HoverEvent; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import com.google.common.math.IntMath; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.apache.logging.log4j.message.FormattedMessage; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; @@ -41,21 +40,11 @@ public class CoverFluidRegulator extends CoverPump { protected TransferMode transferMode = TransferMode.TRANSFER_ANY; - protected int transferAmount = 0; public CoverFluidRegulator(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int mbPerTick) { super(definition, coverableView, attachedSide, tier, mbPerTick); - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip, maxFluidTransferRate * 100); - } - - @Override - protected boolean shouldShowTip() { - return transferMode != TransferMode.TRANSFER_ANY; - } - - public int getTransferAmount() { - return transferAmount; + this.fluidFilterContainer = new FluidFilterContainer(this); } @Override @@ -75,11 +64,12 @@ protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandl } return switch (transferMode) { case TRANSFER_ANY -> GTTransferUtils.transferFluids(sourceHandler, destHandler, transferLimit, - fluidFilter::testFluidStack); - case KEEP_EXACT -> doKeepExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, - this.transferAmount); + fluidFilterContainer::test); + case KEEP_EXACT -> doKeepExact(transferLimit, sourceHandler, destHandler, + fluidFilterContainer::test, + this.fluidFilterContainer.getTransferSize()); case TRANSFER_EXACT -> doTransferExact(transferLimit, sourceHandler, destHandler, - fluidFilter::testFluidStack, this.transferAmount); + fluidFilterContainer::test, this.fluidFilterContainer.getTransferSize()); }; } @@ -88,9 +78,8 @@ protected int doTransferExact(int transferLimit, IFluidHandler sourceHandler, IF int fluidLeftToTransfer = transferLimit; for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { FluidStack sourceFluid = tankProperties.getContents(); - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && - transferMode != TransferMode.TRANSFER_ANY) { - supplyAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(sourceFluid); + if (this.fluidFilterContainer.hasFilter()) { + supplyAmount = this.fluidFilterContainer.getFilter().getTransferLimit(sourceFluid, supplyAmount); } if (fluidLeftToTransfer < supplyAmount) break; @@ -132,9 +121,8 @@ protected int doKeepExact(final int transferLimit, if (transferred >= transferLimit) break; - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && - transferMode != TransferMode.TRANSFER_ANY) { - keepAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(fluidStack); + if (this.fluidFilterContainer.hasFilter()) { + keepAmount = this.fluidFilterContainer.getFilter().getTransferLimit(fluidStack, keepAmount); } // if fluid needs to be moved to meet the Keep Exact value @@ -235,8 +223,11 @@ private static Map collectDistinctFluids(IFluidHandler hand } public void setTransferMode(TransferMode transferMode) { - this.transferMode = transferMode; - this.markDirty(); + if (this.transferMode != transferMode) { + this.transferMode = transferMode; + this.fluidFilterContainer.setMaxTransferSize(getMaxTransferRate()); + this.markDirty(); + } } public TransferMode getTransferMode() { @@ -244,122 +235,87 @@ public TransferMode getTransferMode() { } private boolean shouldDisplayAmountSlider() { - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null) { + if (transferMode == TransferMode.TRANSFER_ANY) { return false; } - return this.transferMode == TransferMode.TRANSFER_EXACT || this.transferMode == TransferMode.KEEP_EXACT; - } - - public String getTransferAmountString() { - return Integer.toString(this.bucketMode == BucketMode.BUCKET ? transferAmount / 1000 : transferAmount); - } - - private String getTransferSizeString() { - int val = transferAmount; - if (this.bucketMode == BucketMode.BUCKET) { - val /= 1000; - } - return val == -1 ? "" : TextFormattingUtil.formatLongToCompactString(val); - } - - protected void getHoverString(List textList) { - ITextComponent keepComponent = new TextComponentString(getTransferSizeString()); - TextComponentTranslation hoverKeep = new TextComponentTranslation( - "cover.fluid_regulator." + transferMode.name().toLowerCase(), this.transferAmount); - keepComponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverKeep)); - textList.add(keepComponent); + return fluidFilterContainer.showGlobalTransferLimitSlider(); } @Override - public void setBucketMode(BucketMode bucketMode) { - super.setBucketMode(bucketMode); - if (this.bucketMode == BucketMode.BUCKET) { - setTransferAmount(transferAmount / 1000 * 1000); - } + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 36); } - private void adjustTransferSize(int amount) { - if (bucketMode == BucketMode.BUCKET) - amount *= 1000; - switch (this.transferMode) { - case TRANSFER_EXACT -> setTransferAmount( - MathHelper.clamp(this.transferAmount + amount, 0, this.maxFluidTransferRate)); - case KEEP_EXACT -> setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, Integer.MAX_VALUE)); - } + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var transferMode = new EnumSyncValue<>(TransferMode.class, this::getTransferMode, this::setTransferMode); + transferMode.updateCacheFromSource(true); + syncManager.syncValue("transfer_mode", transferMode); + + var bucketMode = new EnumSyncValue<>(BucketMode.class, this::getBucketMode, this::setBucketMode); + bucketMode.updateCacheFromSource(true); + syncManager.syncValue("bucket_mode", bucketMode); + + var filterTransferSize = new StringSyncValue(this::getStringTransferRate, this::setStringTransferRate); + filterTransferSize.updateCacheFromSource(true); + + return super.createUI(mainPanel, syncManager) + .child(new EnumRowBuilder<>(TransferMode.class) + .value(transferMode) + .lang("cover.generic.transfer_mode") + .overlay(GTGuiTextures.FLUID_TRANSFER_MODE_OVERLAY) + .build()) + .child(new EnumRowBuilder<>(BucketMode.class) + .value(bucketMode) + .overlay(IKey.str("kL"), IKey.str("L")) + .build() + .child(new TextFieldWidget().widthRel(0.5f).right(0) + .setEnabledIf(w -> shouldDisplayAmountSlider()) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } - private void setTransferAmount(int transferAmount) { - this.transferAmount = transferAmount; - markDirty(); + @Override + public int getMaxTransferRate() { + return switch (this.transferMode) { + case TRANSFER_ANY -> 1; + case TRANSFER_EXACT -> maxFluidTransferRate; + case KEEP_EXACT -> Integer.MAX_VALUE; + }; } @Override - protected String getUITitle() { - return "cover.fluid_regulator.title"; + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.transferMode.ordinal()); } - @SuppressWarnings("UnstableApiUsage") @Override - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - WidgetGroup filterGroup = new WidgetGroup(); - filterGroup.addWidget(new CycleButtonWidget(92, 43, 75, 18, - TransferMode.class, this::getTransferMode, this::setTransferMode) - .setTooltipHoverString("cover.fluid_regulator.transfer_mode.description")); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(110, 64, 38, 18, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget(new IncrementButtonWidget(148, 64, 18, 18, 1, 10, 100, 1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup - .addWidget(new IncrementButtonWidget(92, 64, 18, 18, -1, -10, -100, -1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(111, 70, 36, 11, this::getTransferAmountString, val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount = IntMath.saturatedMultiply(amount, 1000); - } - setTransferAmount(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, - transferMode == TransferMode.TRANSFER_EXACT ? maxFluidTransferRate : Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.6f)); - - stackSizeGroup - .addWidget(new SimpleTextWidget(129, 78, "", 0xFFFFFF, () -> bucketMode.localeName).setScale(0.6f)); - - return super.buildUI(builder.widget(filterGroup).widget(stackSizeGroup), player); + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.transferMode = TransferMode.VALUES[packetBuffer.readByte()]; } @Override public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("TransferMode", transferMode.ordinal()); - tagCompound.setInteger("TransferAmount", transferAmount); tagCompound.setTag("filterv2", new NBTTagCompound()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { + this.transferMode = TransferMode.VALUES[tagCompound.getInteger("TransferMode")]; + this.fluidFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); super.readFromNBT(tagCompound); - this.transferMode = TransferMode.values()[tagCompound.getInteger("TransferMode")]; // legacy NBT tag if (!tagCompound.hasKey("filterv2") && tagCompound.hasKey("TransferAmount")) { - FluidFilter filter = getFluidFilterContainer().getFilterWrapper().getFluidFilter(); - if (filter != null) { - filter.configureFilterTanks(tagCompound.getInteger("TransferAmount")); + if (this.fluidFilterContainer.getFilter() instanceof SimpleFluidFilter simpleFluidFilter) { + simpleFluidFilter + .configureFilterTanks(tagCompound.getInteger("TransferAmount")); } } - this.transferAmount = tagCompound.getInteger("TransferAmount"); } @Override diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index 4c1f097ccee..c781f816bef 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -3,11 +3,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -29,6 +24,15 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.NotNull; public class CoverFluidVoiding extends CoverPump { @@ -39,7 +43,8 @@ public CoverFluidVoiding(@NotNull CoverDefinition definition, @NotNull Coverable @NotNull EnumFacing attachedSide) { super(definition, coverableView, attachedSide, 0, Integer.MAX_VALUE); this.isWorkingAllowed = false; - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip, Integer.MAX_VALUE); + this.fluidFilterContainer = new FluidFilterContainer(this); + this.fluidFilterContainer.setMaxTransferSize(Integer.MAX_VALUE); } @Override @@ -55,39 +60,46 @@ protected void doTransferFluids() { if (myFluidHandler == null) { return; } - GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, + fluidFilterContainer::test); } @Override - protected String getUITitle() { - return "cover.fluid.voiding.title"; + public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, + IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { + Textures.FLUID_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - this.fluidFilter.initUI(20, primaryGroup::addWidget); - - primaryGroup.addWidget(new CycleButtonWidget(10, 92, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 - 22); + } - primaryGroup.addWidget(new CycleButtonWidget(10, 112, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var isWorking = new BooleanSyncValue(this::isWorkingEnabled, this::setWorkingEnabled); + + return super.createUI(mainPanel, syncManager) + .child(new Row().height(18).widthRel(1f) + .marginBottom(2) + .child(new ToggleButton() + .value(isWorking) + .overlay(IKey.dynamic(() -> IKey.lang(this.isWorkingAllowed ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))); + } - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 100 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 100 + 16 + 24); - return builder.build(this, player); + @Override + protected boolean createPumpModeRow() { + return false; } @Override - public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, - IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { - Textures.FLUID_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); + protected boolean createThroughputRow() { + return false; } @Override @@ -120,7 +132,7 @@ public NullFluidTank() { @Override public int fill(FluidStack resource, boolean doFill) { - if (fluidFilter.testFluidStack(resource)) { + if (fluidFilterContainer.test(resource)) { return resource.amount; } return 0; diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java index 4d2290aa13b..3af29c03b3b 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java @@ -2,18 +2,14 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -23,9 +19,17 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; import java.util.function.Predicate; public class CoverFluidVoidingAdvanced extends CoverFluidVoiding { @@ -38,11 +42,6 @@ public CoverFluidVoidingAdvanced(@NotNull CoverDefinition definition, @NotNull C super(definition, coverableView, attachedSide); } - @Override - protected boolean shouldShowTip() { - return voidingMode != VoidingMode.VOID_ANY; - } - @Override protected void doTransferFluids() { IFluidHandler myFluidHandler = getCoverableView().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, @@ -52,8 +51,9 @@ protected void doTransferFluids() { } switch (voidingMode) { case VOID_ANY -> GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, - fluidFilter::testFluidStack); - case VOID_OVERFLOW -> voidOverflow(myFluidHandler, fluidFilter::testFluidStack, this.transferAmount); + fluidFilterContainer::test); + case VOID_OVERFLOW -> voidOverflow(myFluidHandler, fluidFilterContainer::test, + this.transferAmount); } } @@ -72,45 +72,26 @@ protected void voidOverflow(final IFluidHandler sourceHandler, for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { FluidStack sourceFluid = tankProperties.getContents(); - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && + if (this.fluidFilterContainer.hasFilter() && voidingMode == VoidingMode.VOID_OVERFLOW) { - keepAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(sourceFluid); + keepAmount = this.fluidFilterContainer.getFilter() + .getTransferLimit(sourceFluid, getMaxTransferRate()); } if (sourceFluid == null || sourceFluid.amount == 0 || - !getFluidFilterContainer().testFluidStack(sourceFluid, true)) + !getFluidFilterContainer().test(sourceFluid)) continue; sourceFluid.amount = sourceFluid.amount - keepAmount; sourceHandler.drain(sourceFluid, true); } } - @Override - public void setBucketMode(BucketMode bucketMode) { - super.setBucketMode(bucketMode); - if (this.bucketMode == BucketMode.BUCKET) { - setTransferAmount(transferAmount / 1000 * 1000); - } - } - - private void adjustTransferSize(int amount) { - if (bucketMode == BucketMode.BUCKET) - amount *= 1000; - if (this.voidingMode == VoidingMode.VOID_OVERFLOW) { - setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, Integer.MAX_VALUE)); - } - } - - private void setTransferAmount(int transferAmount) { - this.transferAmount = transferAmount; - markDirty(); - } - public int getTransferAmount() { - return this.transferAmount; + return this.fluidFilterContainer.getTransferSize(); } public void setVoidingMode(VoidingMode transferMode) { this.voidingMode = transferMode; + this.fluidFilterContainer.setMaxTransferSize(getMaxTransferRate()); this.markDirty(); } @@ -118,101 +99,64 @@ public VoidingMode getVoidingMode() { return voidingMode; } - private boolean shouldDisplayAmountSlider() { - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null) { - return false; - } - - return this.voidingMode == VoidingMode.VOID_OVERFLOW; + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 20); } - public String getTransferAmountString() { - return Integer.toString(this.bucketMode == BucketMode.BUCKET ? transferAmount / 1000 : transferAmount); + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var voidingMode = new EnumSyncValue<>(VoidingMode.class, this::getVoidingMode, this::setVoidingMode); + syncManager.syncValue("voiding_mode", voidingMode); + + var bucketMode = new EnumSyncValue<>(BucketMode.class, this::getBucketMode, this::setBucketMode); + bucketMode.updateCacheFromSource(true); + syncManager.syncValue("bucket_mode", bucketMode); + + var filterTransferSize = new StringSyncValue(this::getStringTransferRate, this::setStringTransferRate); + var transferTextField = new TextFieldWidget().widthRel(0.5f).right(0); + transferTextField.setEnabled(this.fluidFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW); + + return super.createUI(mainPanel, syncManager) + .child(new EnumRowBuilder<>(VoidingMode.class) + .value(voidingMode) + .lang("cover.voiding.voiding_mode") + .overlay(16, GTGuiTextures.VOIDING_MODE_OVERLAY) + .build()) + .child(new EnumRowBuilder<>(BucketMode.class) + .value(bucketMode) + .overlay(IKey.str("kL"), IKey.str("L")) + .build() + .child(transferTextField + .setEnabledIf(w -> this.fluidFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } @Override - protected String getUITitle() { - return "cover.fluid.voiding.advanced.title"; + protected int getMaxTransferRate() { + return getVoidingMode().maxStackSize; } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - primaryGroup.addWidget(new CycleButtonWidget(92, 15, 75, 18, - VoidingMode.class, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString("cover.voiding.voiding_mode.description")); - - this.initFilterUI(20, primaryGroup::addWidget); - - primaryGroup.addWidget(new CycleButtonWidget(10, 92, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 100 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 100 + 16 + 24); - return buildUI(builder, player); + public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, + IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { + Textures.FLUID_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } - public void initFilterUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.pump.fluid_filter.title")); - widgetGroup.accept(new SlotWidget(fluidFilter.getFilterInventory(), 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(110, 34, 38, 18, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget(new IncrementButtonWidget(148, 34, 18, 18, 1, 10, 100, 1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup - .addWidget(new IncrementButtonWidget(92, 34, 18, 18, -1, -10, -100, -1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(111, 39, 37, 11, this::getTransferAmountString, val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount *= 1000; - } - setTransferAmount(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.6f)); - - stackSizeGroup - .addWidget(new SimpleTextWidget(129, 47, "", 0xFFFFFF, () -> bucketMode.localeName).setScale(0.6f)); - - stackSizeGroup.addWidget(new CycleButtonWidget(114, 53, 30, 20, - BucketMode.class, this::getBucketMode, mode -> { - if (mode != bucketMode) { - setBucketMode(mode); - } - })); - - widgetGroup.accept(stackSizeGroup); - - this.fluidFilter.getFilterWrapper().initUI(y + 15, widgetGroup); - this.fluidFilter.getFilterWrapper().blacklistUI(y + 15, widgetGroup, - () -> voidingMode != VoidingMode.VOID_OVERFLOW); + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.voidingMode = VoidingMode.VALUES[packetBuffer.readByte()]; } @Override - public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, - IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { - Textures.FLUID_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.voidingMode.ordinal()); } @Override @@ -224,8 +168,9 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { - super.readFromNBT(tagCompound); - this.voidingMode = VoidingMode.values()[tagCompound.getInteger("VoidingMode")]; + this.voidingMode = VoidingMode.VALUES[tagCompound.getInteger("VoidingMode")]; + this.fluidFilterContainer.setMaxTransferSize(this.voidingMode.maxStackSize); this.transferAmount = tagCompound.getInteger("TransferAmount"); + super.readFromNBT(tagCompound); } } diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 656fe17f5d8..909fb09e481 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -5,20 +5,19 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; -import gregtech.common.covers.filter.ItemFilter; -import gregtech.common.covers.filter.ItemFilterWrapper; +import gregtech.client.utils.TooltipHelper; +import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.ItemFilterContainer; 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.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -32,25 +31,69 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; public class CoverItemFilter extends CoverBase implements CoverWithUI { protected final String titleLocale; protected final SimpleOverlayRenderer texture; - protected final ItemFilterWrapper itemFilter; + protected final ItemFilterContainer itemFilterContainer; protected ItemFilterMode filterMode = ItemFilterMode.FILTER_INSERT; protected ItemHandlerFiltered itemHandler; public CoverItemFilter(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, - @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture, - ItemFilter itemFilter) { + @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture) { super(definition, coverableView, attachedSide); this.titleLocale = titleLocale; this.texture = texture; - this.itemFilter = new ItemFilterWrapper(this); - this.itemFilter.setItemFilter(itemFilter); - this.itemFilter.setMaxStackSize(1); + this.itemFilterContainer = new ItemFilterContainer(this); + } + + @Override + public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFacing side, + @Nullable EntityPlayer player, @NotNull ItemStack itemStack) { + super.onAttachment(coverableView, side, player, itemStack); + var dropStack = GTUtility.copy(1, itemStack); + this.itemFilterContainer.setFilterStack(dropStack); + } + + @Override + public @NotNull ItemStack getPickItem() { + if (TooltipHelper.isCtrlDown()) + return getCoverableView().getStackForm(); + + return this.itemFilterContainer.getFilterStack(); + } + + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + packetBuffer.writeBoolean(itemFilterContainer.hasFilter()); + if (itemFilterContainer.hasFilter()) { + packetBuffer.writeByte(this.filterMode.ordinal()); + packetBuffer.writeItemStack(this.itemFilterContainer.getFilterStack()); + } + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + if (!packetBuffer.readBoolean()) return; + this.filterMode = ItemFilterMode.VALUES[packetBuffer.readByte()]; + try { + this.itemFilterContainer.setFilterStack(packetBuffer.readItemStack()); + } catch (IOException e) { + GTLog.logger.error("Failed to read filter for CoverItemFilter! %s", getPos().toString()); + } } public void setFilterMode(ItemFilterMode filterMode) { @@ -62,8 +105,11 @@ public ItemFilterMode getFilterMode() { return filterMode; } - public ItemFilterWrapper getItemFilter() { - return this.itemFilter; + @SuppressWarnings("DataFlowIssue") // this cover should always have a filter + public @NotNull BaseFilter getFilter() { + return this.itemFilterContainer.hasFilter() ? + this.itemFilterContainer.getFilter() : + BaseFilter.ERROR_FILTER; } @Override @@ -86,22 +132,34 @@ public boolean canPipePassThrough() { } public boolean testItemStack(ItemStack stack) { - return itemFilter.testItemStack(stack); + return itemFilterContainer.test(stack); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup filterGroup = new WidgetGroup(); - filterGroup.addWidget(new LabelWidget(10, 5, titleLocale)); - filterGroup.addWidget(new CycleButtonWidget(10, 20, 110, 20, - GTUtility.mapToString(ItemFilterMode.values(), it -> it.localeName), - () -> filterMode.ordinal(), (newMode) -> setFilterMode(ItemFilterMode.values()[newMode]))); - this.itemFilter.initUI(45, filterGroup::addWidget); - this.itemFilter.blacklistUI(45, filterGroup::addWidget, () -> true); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 105 + 82) - .widget(filterGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 105) - .build(this, player); + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var filteringMode = new EnumSyncValue<>(ItemFilterMode.class, this::getFilterMode, this::setFilterMode); + + guiSyncManager.syncValue("filtering_mode", filteringMode); + getFilter().getFilterReader().readStack(this.itemFilterContainer.getFilterStack()); + + return getFilter().createPanel(guiSyncManager) + .size(176, 194).padding(7) + .child(CoverWithUI.createTitleRow(getPickItem()).left(4)) + .child(new Column().widthRel(1f).align(Alignment.TopLeft).top(22).coverChildrenHeight() + .child(new EnumRowBuilder<>(ItemFilterMode.class) + .value(filteringMode) + .lang("cover.filter.mode.title") + .overlay(16, GTGuiTextures.FILTER_MODE_OVERLAY) + .build()) + .child(new Rectangle().setColor(UI_TEXT_COLOR).asWidget() + .height(1).widthRel(0.95f).margin(0, 4)) + .child(getFilter().createWidgets(guiSyncManager).left(0))) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); } @Override @@ -114,18 +172,20 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("FilterMode", filterMode.ordinal()); - tagCompound.setBoolean("IsBlacklist", this.itemFilter.isBlacklistFilter()); - NBTTagCompound filterComponent = new NBTTagCompound(); - this.itemFilter.getItemFilter().writeToNBT(filterComponent); - tagCompound.setTag("Filter", filterComponent); + tagCompound.setTag("Filter", this.itemFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); - this.filterMode = ItemFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - this.itemFilter.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); + this.filterMode = ItemFilterMode.VALUES[tagCompound.getInteger("FilterMode")]; + var filterTag = tagCompound.getCompoundTag("Filter"); + if (!filterTag.hasKey("FilterInventory")) { + this.itemFilterContainer.setFilterStack(getDefinition().getDropItemStack()); + } else { + this.itemFilterContainer.deserializeNBT(filterTag); + } + this.itemFilterContainer.handleLegacyNBT(tagCompound); } @Override @@ -152,7 +212,7 @@ public ItemHandlerFiltered(IItemHandler delegate) { @NotNull @Override public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT || !itemFilter.testItemStack(stack)) { + if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT || !itemFilterContainer.test(stack)) { return stack; } return super.insertItem(slot, stack, simulate); @@ -163,7 +223,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate public ItemStack extractItem(int slot, int amount, boolean simulate) { if (getFilterMode() != ItemFilterMode.FILTER_INSERT) { ItemStack result = super.extractItem(slot, amount, true); - if (result.isEmpty() || !itemFilter.testItemStack(result)) { + if (result.isEmpty() || !itemFilterContainer.test(result)) { return ItemStack.EMPTY; } return simulate ? result : super.extractItem(slot, amount, false); diff --git a/src/main/java/gregtech/common/covers/CoverItemVoiding.java b/src/main/java/gregtech/common/covers/CoverItemVoiding.java index 9a515b670d3..977968bbab1 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoiding.java @@ -3,11 +3,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -26,6 +21,16 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.NotNull; public class CoverItemVoiding extends CoverConveyor { @@ -60,7 +65,7 @@ void voidAny(IItemHandler myItemHandler) { if (sourceStack.isEmpty()) { continue; } - if (!itemFilterContainer.testItemStack(sourceStack)) { + if (!itemFilterContainer.test(sourceStack)) { continue; } myItemHandler.extractItem(srcIndex, Integer.MAX_VALUE, false); @@ -68,29 +73,40 @@ void voidAny(IItemHandler myItemHandler) { } @Override - protected String getUITitle() { - return "cover.item.voiding.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 - 22); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - this.itemFilterContainer.initUI(20, primaryGroup::addWidget); - - primaryGroup - .addWidget(new CycleButtonWidget(10, 92 + 23, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112 + 23, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 125 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 125 + 16 + 24); - return builder.build(this, player); + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var isWorking = new BooleanSyncValue(this::isWorkingEnabled, this::setWorkingEnabled); + + return super.createUI(mainPanel, guiSyncManager) + .child(new Row().height(18).widthRel(1f) + .marginBottom(2) + .child(new ToggleButton() + .value(isWorking) + .overlay(IKey.dynamic(() -> IKey.lang(this.isWorkingAllowed ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))); + } + + @Override + protected boolean createThroughputRow() { + return false; + } + + @Override + protected boolean createConveyorModeRow() { + return false; + } + + @Override + protected boolean createDistributionModeRow() { + return false; } @Override @@ -137,7 +153,7 @@ public ItemStack getStackInSlot(int slot) { @NotNull @Override public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - if (!itemFilterContainer.testItemStack(stack)) { + if (!itemFilterContainer.test(stack)) { return stack; } return ItemStack.EMPTY; diff --git a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java index 62d2844aaa3..fe7a52f64e5 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java @@ -2,18 +2,14 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -21,10 +17,19 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import java.util.Map; -import java.util.function.Consumer; public class CoverItemVoidingAdvanced extends CoverItemVoiding { @@ -34,7 +39,7 @@ public CoverItemVoidingAdvanced(@NotNull CoverDefinition definition, @NotNull Co @NotNull EnumFacing attachedSide) { super(definition, coverableView, attachedSide); this.voidingMode = VoidingMode.VOID_ANY; - this.itemFilterContainer.setMaxStackSize(1); + this.itemFilterContainer.setMaxTransferSize(1); } @Override @@ -56,13 +61,11 @@ protected void voidOverflow(IItemHandler myItemHandler) { for (TypeItemInfo typeItemInfo : itemTypeCount.values()) { int itemToVoidAmount = 0; - if (getItemFilterContainer().getFilterWrapper().getItemFilter() == null) { - itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getTransferStackSize(); + if (!getItemFilterContainer().hasFilter()) { + itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getTransferSize(); } else { - if (itemFilterContainer.testItemStack(typeItemInfo.itemStack)) { - Object matchedSlot = itemFilterContainer.matchItemStack(typeItemInfo.itemStack); - itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getSlotTransferLimit(matchedSlot); - } + var result = itemFilterContainer.match(typeItemInfo.itemStack); + itemToVoidAmount = result.getItemStack().getCount(); } if (itemToVoidAmount <= 0) { @@ -86,75 +89,41 @@ protected void voidOverflow(IItemHandler myItemHandler) { } @Override - protected String getUITitle() { - return "cover.item.voiding.advanced.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 18); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - primaryGroup.addWidget(new CycleButtonWidget(91, 14, 75, 20, - VoidingMode.class, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString("cover.voiding.voiding_mode.description")); - - this.initFilterUI(20, primaryGroup::addWidget); - - primaryGroup - .addWidget(new CycleButtonWidget(10, 92 + 23, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112 + 23, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 125 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 125 + 16 + 24); - return buildUI(builder, player); + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var voidingMode = new EnumSyncValue<>(VoidingMode.class, this::getVoidingMode, this::setVoidingMode); + guiSyncManager.syncValue("voiding_mode", voidingMode); + + var filterTransferSize = new StringSyncValue( + () -> String.valueOf(this.itemFilterContainer.getTransferSize()), + s -> this.itemFilterContainer.setTransferSize(Integer.parseInt(s))); + filterTransferSize.updateCacheFromSource(true); + var transferTextField = new TextFieldWidget().widthRel(0.5f).right(0); + transferTextField.setEnabled(this.itemFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW); + + return super.createUI(mainPanel, guiSyncManager) + .child(new EnumRowBuilder<>(VoidingMode.class) + .value(voidingMode) + .lang("cover.voiding.voiding_mode") + .overlay(16, GTGuiTextures.VOIDING_MODE_OVERLAY) + .build()) + .child(new Row().right(0).coverChildrenHeight() + .child(transferTextField + .setEnabledIf(w -> this.itemFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } - // Basically the item filter container GUI code, with different Y widget positioning - public void initFilterUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.conveyor.item_filter.title")); - widgetGroup.accept(new SlotWidget(itemFilterContainer.getFilterInventory(), 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup( - () -> itemFilterContainer.getFilterWrapper().getItemFilter() == null && - voidingMode == VoidingMode.VOID_OVERFLOW); - stackSizeGroup.addWidget(new ImageWidget(111, 34, 35, 20, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget( - new IncrementButtonWidget(146, 34, 20, 20, 1, 8, 64, 512, itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup.addWidget(new IncrementButtonWidget(91, 34, 20, 20, -1, -8, -64, -512, - itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(113, 41, 31, 20, - () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { - if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, voidingMode.maxStackSize)); - }) - .setCentered(true) - .setNumbersOnly(1, Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.9f)); - - widgetGroup.accept(stackSizeGroup); - - this.itemFilterContainer.getFilterWrapper().initUI(y + 38, widgetGroup); - - this.itemFilterContainer.getFilterWrapper().blacklistUI(y + 38, widgetGroup, - () -> voidingMode != VoidingMode.VOID_OVERFLOW); + @Override + protected int getMaxStackSize() { + return getVoidingMode().maxStackSize; } @Override @@ -165,7 +134,7 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO public void setVoidingMode(VoidingMode voidingMode) { this.voidingMode = voidingMode; - this.itemFilterContainer.setMaxStackSize(voidingMode.maxStackSize); + this.itemFilterContainer.setMaxTransferSize(getMaxStackSize()); this.getCoverableView().markDirty(); } @@ -173,6 +142,18 @@ public VoidingMode getVoidingMode() { return voidingMode; } + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.voidingMode.ordinal()); + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.voidingMode = VoidingMode.VALUES[packetBuffer.readByte()]; + } + @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); @@ -181,7 +162,8 @@ public void writeToNBT(NBTTagCompound tagCompound) { @Override public void readFromNBT(NBTTagCompound tagCompound) { + this.voidingMode = VoidingMode.VALUES[tagCompound.getInteger("VoidMode")]; + this.itemFilterContainer.setMaxTransferSize(this.voidingMode.maxStackSize); super.readFromNBT(tagCompound); - this.voidingMode = VoidingMode.values()[tagCompound.getInteger("VoidMode")]; } } diff --git a/src/main/java/gregtech/common/covers/CoverMachineController.java b/src/main/java/gregtech/common/covers/CoverMachineController.java index 423a44fccd3..517a9bc5711 100644 --- a/src/main/java/gregtech/common/covers/CoverMachineController.java +++ b/src/main/java/gregtech/common/covers/CoverMachineController.java @@ -120,7 +120,7 @@ public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManag guiSyncManager.syncValue("inverted", invertedValue); return GTGuis.createPanel(this, 176, 112) - .child(createTitleRow()) + .child(CoverWithUI.createTitleRow(getPickItem())) .child(new Column() .widthRel(1.0f).margin(7, 0) .top(24).coverChildrenHeight() diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 961e349be6b..e91a59118a6 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -1,6 +1,5 @@ package gregtech.common.covers; -import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; @@ -9,14 +8,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.ImageWidget; -import gregtech.api.gui.widgets.IncrementButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.TextFieldWidget2; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; @@ -47,13 +40,23 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; -import com.google.common.math.IntMath; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; -import java.util.function.IntSupplier; - public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable { public final int tier; @@ -65,7 +68,7 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected int fluidLeftToTransferLastSecond; private CoverableFluidHandlerWrapper fluidHandlerWrapper; protected boolean isWorkingAllowed = true; - protected FluidFilterContainer fluidFilter; + protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @@ -75,25 +78,35 @@ public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView cov this.maxFluidTransferRate = mbPerTick; this.transferRate = mbPerTick; this.fluidLeftToTransferLastSecond = transferRate; - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip); + this.fluidFilterContainer = new FluidFilterContainer(this); + } + + public void setStringTransferRate(String s) { + this.fluidFilterContainer.setTransferSize( + getBucketMode() == BucketMode.MILLI_BUCKET ? + Integer.parseInt(s) : + Integer.parseInt(s) * 1000); } - protected boolean shouldShowTip() { - return false; + public String getStringTransferRate() { + return String.valueOf(getBucketMode() == BucketMode.MILLI_BUCKET ? + this.fluidFilterContainer.getTransferSize() : + this.fluidFilterContainer.getTransferSize() / 1000); } public void setTransferRate(int transferRate) { - this.transferRate = transferRate; + if (bucketMode == BucketMode.BUCKET) transferRate *= 1000; + this.transferRate = MathHelper.clamp(transferRate, 1, maxFluidTransferRate); markDirty(); } public int getTransferRate() { - return transferRate; + return bucketMode == BucketMode.BUCKET ? transferRate / 1000 : transferRate; } protected void adjustTransferRate(int amount) { amount *= this.bucketMode == BucketMode.BUCKET ? 1000 : 1; - setTransferRate(MathHelper.clamp(transferRate + amount, 1, maxFluidTransferRate)); + setTransferRate(this.transferRate + amount); } public void setPumpMode(PumpMode pumpMode) { @@ -127,7 +140,7 @@ protected void setManualImportExportMode(ManualImportExportMode manualImportExpo } public FluidFilterContainer getFluidFilterContainer() { - return fluidFilter; + return fluidFilterContainer; } @Override @@ -157,100 +170,124 @@ protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandl int transferLimit) { if (pumpMode == PumpMode.IMPORT) { return GTTransferUtils.transferFluids(fluidHandler, myFluidHandler, transferLimit, - fluidFilter::testFluidStack); + fluidFilterContainer::test); } else if (pumpMode == PumpMode.EXPORT) { return GTTransferUtils.transferFluids(myFluidHandler, fluidHandler, transferLimit, - fluidFilter::testFluidStack); + fluidFilterContainer::test); } return 0; } protected boolean checkInputFluid(FluidStack fluidStack) { - return fluidFilter.testFluidStack(fluidStack); + return fluidFilterContainer.test(fluidStack); } - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - return builder.build(this, player); + @Override + public boolean usesMui2() { + return true; } - protected String getUITitle() { - return "cover.pump.title"; + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192); + + getFluidFilterContainer().setMaxTransferSize(getMaxTransferRate()); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createUI(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var manualIOmode = new EnumSyncValue<>(ManualImportExportMode.class, + this::getManualImportExportMode, this::setManualImportExportMode); + manualIOmode.updateCacheFromSource(true); + + var throughput = new IntSyncValue(this::getTransferRate, this::setTransferRate); + throughput.updateCacheFromSource(true); + + var throughputString = new StringSyncValue( + throughput::getStringValue, + throughput::setStringValue); + throughputString.updateCacheFromSource(true); + + var pumpMode = new EnumSyncValue<>(PumpMode.class, this::getPumpMode, this::setPumpMode); + pumpMode.updateCacheFromSource(true); + + syncManager.syncValue("manual_io", manualIOmode); + syncManager.syncValue("pump_mode", pumpMode); + syncManager.syncValue("throughput", throughput); + + var column = new Column().top(24).margin(7, 0) + .widthRel(1f).coverChildrenHeight(); + + if (createThroughputRow()) + column.child(new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ButtonWidget<>() + .left(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() - getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(false)))) + .child(new TextFieldWidget() + .left(18).right(18) + .setTextColor(Color.WHITE.darker(1)) + .setNumbers(1, maxFluidTransferRate) + .value(throughputString) + .background(GTGuiTextures.DISPLAY)) + .child(new ButtonWidget<>() + .right(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() + getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(true))))); + + if (createFilterRow()) + column.child(getFluidFilterContainer() + .initUI(mainPanel, syncManager)); + + if (createManualIOModeRow()) + column.child(new EnumRowBuilder<>(ManualImportExportMode.class) + .value(manualIOmode) + .lang("cover.generic.manual_io") + .overlay(GTGuiTextures.MANUAL_IO_OVERLAY) + .build()); + + if (createPumpModeRow()) + column.child(new EnumRowBuilder<>(PumpMode.class) + .value(pumpMode) + .lang("cover.pump.mode") + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) // todo pump mode overlays + .build()); + + return column; + } + + protected boolean createThroughputRow() { + return true; } - @SuppressWarnings("UnstableApiUsage") - @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle(), GTValues.VN[tier])); - - primaryGroup.addWidget(new ImageWidget(44, 20, 62, 20, GuiTextures.DISPLAY)); - - primaryGroup.addWidget(new IncrementButtonWidget(136, 20, 30, 20, 1, 10, 100, 1000, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - primaryGroup.addWidget(new IncrementButtonWidget(10, 20, 34, 20, -1, -10, -100, -1000, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - - TextFieldWidget2 textField = new TextFieldWidget2(45, 26, 60, 20, () -> bucketMode == BucketMode.BUCKET ? - Integer.toString(transferRate / 1000) : Integer.toString(transferRate), val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount = IntMath.saturatedMultiply(amount, 1000); - } - setTransferRate(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, - bucketMode == BucketMode.BUCKET ? maxFluidTransferRate / 1000 : maxFluidTransferRate) - .setMaxLength(8); - primaryGroup.addWidget(textField); - - primaryGroup.addWidget(new CycleButtonWidget(106, 20, 30, 20, - BucketMode.class, this::getBucketMode, mode -> { - if (mode != bucketMode) { - setBucketMode(mode); - } - })); - - primaryGroup.addWidget(new CycleButtonWidget(10, 43, 75, 18, - PumpMode.class, this::getPumpMode, this::setPumpMode)); - - primaryGroup.addWidget(new CycleButtonWidget(7, 160, 116, 20, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - this.fluidFilter.initUI(88, primaryGroup::addWidget); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 184 + 82) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 184); - return buildUI(builder, player); - } - - public static Function getTextFieldValidator(IntSupplier maxSupplier) { - int min = 1; - return val -> { - if (val.isEmpty()) { - return String.valueOf(min); - } - int max = maxSupplier.getAsInt(); - int num; - try { - num = Integer.parseInt(val); - } catch (NumberFormatException ignored) { - return String.valueOf(max); - } - if (num < min) { - return String.valueOf(min); - } - if (num > max) { - return String.valueOf(max); - } - return val; - }; + protected boolean createFilterRow() { + return true; + } + + protected boolean createManualIOModeRow() { + return true; + } + + protected boolean createPumpModeRow() { + return true; + } + + protected int getMaxTransferRate() { + return 1; } @Override @@ -274,13 +311,15 @@ public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { @Override public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.writeInitialSyncData(packetBuffer); - packetBuffer.writeEnumValue(pumpMode); + packetBuffer.writeByte(pumpMode.ordinal()); + getFluidFilterContainer().writeInitialSyncData(packetBuffer); } @Override public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); - this.pumpMode = packetBuffer.readEnumValue(PumpMode.class); + this.pumpMode = PumpMode.VALUES[packetBuffer.readByte()]; + getFluidFilterContainer().readInitialSyncData(packetBuffer); } @Override @@ -295,7 +334,7 @@ public boolean canInteractWithOutputSide() { @Override public void onRemoval() { - dropInventoryContents(fluidFilter.getFilterInventory()); + dropInventoryContents(fluidFilterContainer); } @Override @@ -344,18 +383,21 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { tagCompound.setInteger("DistributionMode", distributionMode.ordinal()); tagCompound.setBoolean("WorkingAllowed", isWorkingAllowed); tagCompound.setInteger("ManualImportExportMode", manualImportExportMode.ordinal()); - tagCompound.setTag("Filter", fluidFilter.serializeNBT()); + tagCompound.setInteger("BucketMode", bucketMode.ordinal()); + tagCompound.setTag("Filter", fluidFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); - this.pumpMode = PumpMode.values()[tagCompound.getInteger("PumpMode")]; - this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.pumpMode = PumpMode.VALUES[tagCompound.getInteger("PumpMode")]; + this.distributionMode = DistributionMode.VALUES[tagCompound.getInteger("DistributionMode")]; this.isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); - this.manualImportExportMode = ManualImportExportMode.values()[tagCompound.getInteger("ManualImportExportMode")]; - this.fluidFilter.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.manualImportExportMode = ManualImportExportMode.VALUES[tagCompound.getInteger("ManualImportExportMode")]; + this.bucketMode = BucketMode.VALUES[tagCompound.getInteger("BucketMode")]; + this.fluidFilterContainer.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.fluidFilterContainer.handleLegacyNBT(tagCompound); } @Override @@ -369,6 +411,7 @@ public enum PumpMode implements IStringSerializable, IIOMode { IMPORT("cover.pump.mode.import"), EXPORT("cover.pump.mode.export"); + public static final PumpMode[] VALUES = values(); public final String localeName; PumpMode(String localeName) { @@ -392,6 +435,7 @@ public enum BucketMode implements IStringSerializable { BUCKET("cover.bucket.mode.bucket"), MILLI_BUCKET("cover.bucket.mode.milli_bucket"); + public static final BucketMode[] VALUES = values(); public final String localeName; BucketMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 902ffcd62f4..883fe18f9ec 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -1,27 +1,34 @@ package gregtech.common.covers; +import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.ModularUI.Builder; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.pipelike.itempipe.net.ItemNetHandler; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.items.IItemHandler; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -36,7 +43,7 @@ public CoverRoboticArm(@NotNull CoverDefinition definition, @NotNull CoverableVi @NotNull EnumFacing attachedSide, int tier, int itemsPerSecond) { super(definition, coverableView, attachedSide, tier, itemsPerSecond); this.transferMode = TransferMode.TRANSFER_ANY; - this.itemFilterContainer.setMaxStackSize(1); + this.itemFilterContainer.setMaxTransferSize(1); } @Override @@ -72,16 +79,17 @@ protected int doTransferExact(IItemHandler itemHandler, IItemHandler myItemHandl while (iterator.hasNext()) { TypeItemInfo sourceInfo = sourceItemAmount.get(iterator.next()); int itemAmount = sourceInfo.totalCount; - int itemToMoveAmount = itemFilterContainer.getSlotTransferLimit(sourceInfo.filterSlot); + int itemToMoveAmount = itemFilterContainer.getTransferLimit(sourceInfo.itemStack); - // if smart item filter - if (itemFilterContainer.getFilterWrapper().getItemFilter() instanceof SmartItemFilter) { - if (itemFilterContainer.getTransferStackSize() > 1 && itemToMoveAmount * 2 <= itemAmount) { + // if smart item filter and whitelist + if (itemFilterContainer.getFilter() instanceof SmartItemFilter && + !itemFilterContainer.isBlacklistFilter()) { + if (itemFilterContainer.getTransferSize() > 1 && itemToMoveAmount * 2 <= itemAmount) { // get the max we can extract from the item filter variable int maxMultiplier = Math.floorDiv(maxTransferAmount, itemToMoveAmount); // multiply up to the total count of all the items - itemToMoveAmount *= Math.min(itemFilterContainer.getTransferStackSize(), maxMultiplier); + itemToMoveAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); } } @@ -115,24 +123,24 @@ protected int doTransferExact(IItemHandler itemHandler, IItemHandler myItemHandl } protected int doKeepExact(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - Map currentItemAmount = doCountDestinationInventoryItemsByMatchIndex(itemHandler, + Map currentItemAmount = doCountDestinationInventoryItemsByMatchIndex(itemHandler, myItemHandler); - Map sourceItemAmounts = doCountDestinationInventoryItemsByMatchIndex(myItemHandler, + Map sourceItemAmounts = doCountDestinationInventoryItemsByMatchIndex(myItemHandler, itemHandler); - Iterator iterator = sourceItemAmounts.keySet().iterator(); + Iterator iterator = sourceItemAmounts.keySet().iterator(); while (iterator.hasNext()) { - Object filterSlotIndex = iterator.next(); + int filterSlotIndex = iterator.next(); GroupItemInfo sourceInfo = sourceItemAmounts.get(filterSlotIndex); - int itemToKeepAmount = itemFilterContainer.getSlotTransferLimit(sourceInfo.filterSlot); + int itemToKeepAmount = itemFilterContainer.getTransferLimit(sourceInfo.filterSlot); // only run multiplier for smart item - if (itemFilterContainer.getFilterWrapper().getItemFilter() instanceof SmartItemFilter) { - if (itemFilterContainer.getTransferStackSize() > 1 && itemToKeepAmount * 2 <= sourceInfo.totalCount) { + if (itemFilterContainer.getFilter() instanceof SmartItemFilter) { + if (itemFilterContainer.getTransferSize() > 1 && itemToKeepAmount * 2 <= sourceInfo.totalCount) { // get the max we can keep from the item filter variable int maxMultiplier = Math.floorDiv(sourceInfo.totalCount, itemToKeepAmount); // multiply up to the total count of all the items - itemToKeepAmount *= Math.min(itemFilterContainer.getTransferStackSize(), maxMultiplier); + itemToKeepAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); } } @@ -163,9 +171,13 @@ public void clearBuffer() { } public void setTransferMode(TransferMode transferMode) { - this.transferMode = transferMode; - this.getCoverableView().markDirty(); - this.itemFilterContainer.setMaxStackSize(transferMode.maxStackSize); + if (this.transferMode != transferMode) { + this.transferMode = transferMode; + this.getCoverableView().markDirty(); + this.itemFilterContainer.setMaxTransferSize(transferMode.maxStackSize); + writeCustomData(GregtechDataCodes.UPDATE_TRANSFER_MODE, + buffer -> buffer.writeByte(this.transferMode.ordinal())); + } } public TransferMode getTransferMode() { @@ -180,44 +192,60 @@ private boolean shouldDisplayAmountSlider() { } @Override - protected String getUITitle() { - return "cover.robotic_arm.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 36 + 18 + 2); + } + + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + EnumSyncValue transferMode = new EnumSyncValue<>(TransferMode.class, this::getTransferMode, + this::setTransferMode); + guiSyncManager.syncValue("transfer_mode", transferMode); + + var filterTransferSize = new StringSyncValue( + () -> String.valueOf(this.itemFilterContainer.getTransferSize()), + s -> this.itemFilterContainer.setTransferSize(Integer.parseInt(s))); + filterTransferSize.updateCacheFromSource(true); + + return super.createUI(mainPanel, guiSyncManager) + .child(new EnumRowBuilder<>(TransferMode.class) + .value(transferMode) + .lang("cover.generic.transfer_mode") + .overlay(GTGuiTextures.TRANSFER_MODE_OVERLAY) + .build()) + .child(new Row().right(0).coverChildrenHeight() + .child(new TextFieldWidget().widthRel(0.5f).right(0) + .setEnabledIf(w -> shouldDisplayAmountSlider()) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); + } + + @Override + protected int getMaxStackSize() { + return getTransferMode().maxStackSize; } @Override - protected ModularUI buildUI(Builder builder, EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new CycleButtonWidget(91, 45, 75, 20, - TransferMode.class, this::getTransferMode, this::setTransferMode) - .setTooltipHoverString("cover.robotic_arm.transfer_mode.description")); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(111, 70, 35, 20, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget( - new IncrementButtonWidget(146, 70, 20, 20, 1, 8, 64, 512, itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup.addWidget(new IncrementButtonWidget(91, 70, 20, 20, -1, -8, -64, -512, - itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(113, 77, 31, 20, - () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { - if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, transferMode.maxStackSize)); - }) - .setNumbersOnly(1, transferMode.maxStackSize) - .setMaxLength(4) - .setScale(0.9f)); - - primaryGroup.addWidget(stackSizeGroup); - - return super.buildUI(builder.widget(primaryGroup), player); + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.transferMode.ordinal()); + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.transferMode = TransferMode.VALUES[packetBuffer.readByte()]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } + + @Override + public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { + super.readCustomData(discriminator, buf); + if (discriminator == GregtechDataCodes.UPDATE_TRANSFER_MODE) { + this.transferMode = TransferMode.VALUES[buf.readByte()]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } } @Override @@ -228,7 +256,8 @@ public void writeToNBT(NBTTagCompound tagCompound) { @Override public void readFromNBT(NBTTagCompound tagCompound) { + this.transferMode = TransferMode.VALUES[tagCompound.getInteger("TransferMode")]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); super.readFromNBT(tagCompound); - this.transferMode = TransferMode.values()[tagCompound.getInteger("TransferMode")]; } } diff --git a/src/main/java/gregtech/common/covers/DistributionMode.java b/src/main/java/gregtech/common/covers/DistributionMode.java index 24268bdc6a0..c704d045b18 100644 --- a/src/main/java/gregtech/common/covers/DistributionMode.java +++ b/src/main/java/gregtech/common/covers/DistributionMode.java @@ -10,6 +10,7 @@ public enum DistributionMode implements IStringSerializable { ROUND_ROBIN_PRIO("cover.conveyor.distribution.round_robin"), INSERT_FIRST("cover.conveyor.distribution.first_insert"); + public static final DistributionMode[] VALUES = values(); public final String localeName; DistributionMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/FluidFilterMode.java b/src/main/java/gregtech/common/covers/FluidFilterMode.java index ee372ff8b09..e26c6192e8b 100644 --- a/src/main/java/gregtech/common/covers/FluidFilterMode.java +++ b/src/main/java/gregtech/common/covers/FluidFilterMode.java @@ -1,11 +1,14 @@ package gregtech.common.covers; -public enum FluidFilterMode implements IFilterMode { +import net.minecraft.util.IStringSerializable; + +public enum FluidFilterMode implements IStringSerializable { FILTER_FILL("cover.fluid_filter.mode.filter_fill"), FILTER_DRAIN("cover.fluid_filter.mode.filter_drain"), FILTER_BOTH("cover.fluid_filter.mode.filter_both"); + public static final FluidFilterMode[] VALUES = values(); public final String localeName; FluidFilterMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/IFilterMode.java b/src/main/java/gregtech/common/covers/IFilterMode.java deleted file mode 100644 index ecc0fde802f..00000000000 --- a/src/main/java/gregtech/common/covers/IFilterMode.java +++ /dev/null @@ -1,6 +0,0 @@ -package gregtech.common.covers; - -public interface IFilterMode { - - String getName(); -} diff --git a/src/main/java/gregtech/common/covers/ItemFilterMode.java b/src/main/java/gregtech/common/covers/ItemFilterMode.java index 2a871e2984e..6d612915161 100644 --- a/src/main/java/gregtech/common/covers/ItemFilterMode.java +++ b/src/main/java/gregtech/common/covers/ItemFilterMode.java @@ -1,11 +1,14 @@ package gregtech.common.covers; -public enum ItemFilterMode implements IFilterMode { +import net.minecraft.util.IStringSerializable; + +public enum ItemFilterMode implements IStringSerializable { FILTER_INSERT("cover.filter.mode.filter_insert"), FILTER_EXTRACT("cover.filter.mode.filter_extract"), FILTER_BOTH("cover.filter.mode.filter_both"); + public static final ItemFilterMode[] VALUES = values(); public final String localeName; ItemFilterMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/ManualImportExportMode.java b/src/main/java/gregtech/common/covers/ManualImportExportMode.java index d044322425c..df3942d7163 100644 --- a/src/main/java/gregtech/common/covers/ManualImportExportMode.java +++ b/src/main/java/gregtech/common/covers/ManualImportExportMode.java @@ -10,6 +10,7 @@ public enum ManualImportExportMode implements IStringSerializable { FILTERED("cover.universal.manual_import_export.mode.filtered"), UNFILTERED("cover.universal.manual_import_export.mode.unfiltered"); + public static final ManualImportExportMode[] VALUES = values(); public final String localeName; ManualImportExportMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/TransferMode.java b/src/main/java/gregtech/common/covers/TransferMode.java index ebf708dfdf4..2f278c88ce4 100644 --- a/src/main/java/gregtech/common/covers/TransferMode.java +++ b/src/main/java/gregtech/common/covers/TransferMode.java @@ -8,8 +8,9 @@ public enum TransferMode implements IStringSerializable { TRANSFER_ANY("cover.robotic_arm.transfer_mode.transfer_any", 1), TRANSFER_EXACT("cover.robotic_arm.transfer_mode.transfer_exact", 1024), - KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", 1024); + KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", Integer.MAX_VALUE); + public static final TransferMode[] VALUES = values(); public final String localeName; public final int maxStackSize; diff --git a/src/main/java/gregtech/common/covers/VoidingMode.java b/src/main/java/gregtech/common/covers/VoidingMode.java index 48aa9d0b8de..b7e85666f65 100644 --- a/src/main/java/gregtech/common/covers/VoidingMode.java +++ b/src/main/java/gregtech/common/covers/VoidingMode.java @@ -7,8 +7,9 @@ public enum VoidingMode implements IStringSerializable { VOID_ANY("cover.voiding.voiding_mode.void_any", 1), - VOID_OVERFLOW("cover.voiding.voiding_mode.void_overflow", 1024); + VOID_OVERFLOW("cover.voiding.voiding_mode.void_overflow", Integer.MAX_VALUE); + public static final VoidingMode[] VALUES = values(); public final String localeName; public final int maxStackSize; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java index 32239be9036..56d7eb246c9 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java @@ -92,7 +92,7 @@ public ModularUI createUI(EntityPlayer player) { // "cover.generic.advanced_detector.invert_label")); group.addWidget( new CycleButtonWidget(10, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isInverted, this::setInverted, - "cover.machine_controller.normal", "cover.machine_controller.inverted") + "cover.advanced_energy_detector.normal", "cover.advanced_energy_detector.inverted") .setTooltipHoverString("cover.generic.advanced_detector.invert_tooltip")); group.addWidget( new CycleButtonWidget(94, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isLatched, this::setLatched, @@ -145,7 +145,7 @@ public void update() { for (IFluidTankProperties properties : tankProperties) { FluidStack contents = properties.getContents(); - if (contents != null && fluidFilter.testFluidStack(contents)) + if (contents != null && fluidFilter.test(contents)) storedFluid += contents.amount; } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java index 7d992674a93..e2475756fd5 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java @@ -78,7 +78,7 @@ public ModularUI createUI(EntityPlayer player) { // "cover.generic.advanced_detector.invert_label")); group.addWidget( new CycleButtonWidget(10, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isInverted, this::setInverted, - "cover.machine_controller.normal", "cover.machine_controller.inverted") + "cover.advanced_energy_detector.normal", "cover.advanced_energy_detector.inverted") .setTooltipHoverString("cover.generic.advanced_detector.invert_tooltip")); // group.addWidget(new LabelWidget(10, 5 + 4 * (SIZE + PADDING), // "cover.generic.advanced_detector.latch_label")); @@ -151,7 +151,7 @@ public void update() { int storedItems = 0; for (int i = 0; i < itemHandler.getSlots(); i++) { - if (itemFilter.testItemStack(itemHandler.getStackInSlot(i))) + if (itemFilter.test(itemHandler.getStackInSlot(i))) storedItems += itemHandler.getStackInSlot(i).getCount(); } diff --git a/src/main/java/gregtech/common/covers/filter/BaseFilter.java b/src/main/java/gregtech/common/covers/filter/BaseFilter.java new file mode 100644 index 00000000000..ae72a78626d --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/BaseFilter.java @@ -0,0 +1,183 @@ +package gregtech.common.covers.filter; + +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.readers.BaseFilterReader; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fluids.FluidStack; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class BaseFilter implements IFilter { + + public static final BaseFilter ERROR_FILTER = new BaseFilter() { + + private final BaseFilterReader filterReader = new BaseFilterReader(ItemStack.EMPTY, 0); + + @Override + public BaseFilterReader getFilterReader() { + return this.filterReader; + } + + @Override + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("error", 100, 100) + .child(createWidgets(syncManager)); + } + + @Override + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("error", 100, 100) + .child(createWidgets(syncManager)); + } + + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + return IKey.lang("INVALID FILTER").alignment(Alignment.Center).asWidget(); + } + + @Override + public FilterType getType() { + return FilterType.ITEM; + } + }; + protected IDirtyNotifiable dirtyNotifiable; + + public abstract BaseFilterReader getFilterReader(); + + public final ItemStack getContainerStack() { + return this.getFilterReader().getContainer(); + } + + public static @Nullable BaseFilter getFilterFromStack(ItemStack stack) { + if (stack.getItem() instanceof MetaItemmetaItem) { + var metaValueItem = metaItem.getItem(stack); + var factory = metaValueItem == null ? null : metaValueItem.getFilterFactory(); + if (factory != null) + return factory.create(stack); + } + return null; + } + + public final void setBlacklistFilter(boolean blacklistFilter) { + this.getFilterReader().setBlacklistFilter(blacklistFilter); + markDirty(); + } + + @Override + public final MatchResult match(Object toMatch) { + if (toMatch instanceof ItemStack stack) { + return matchItem(stack); + } else if (toMatch instanceof FluidStack stack) { + return matchFluid(stack); + } + return MatchResult.NONE; + } + + public MatchResult matchFluid(FluidStack fluidStack) { + return MatchResult.NONE; + } + + public MatchResult matchItem(ItemStack itemStack) { + return MatchResult.NONE; + } + + @Override + public final boolean test(Object toTest) { + boolean b = false; + if (toTest instanceof ItemStack stack) { + b = testItem(stack); + } else if (toTest instanceof FluidStack stack) { + b = testFluid(stack); + } + return b != isBlacklistFilter(); + } + + public boolean testFluid(FluidStack toTest) { + return false; + } + + public boolean testItem(ItemStack toTest) { + return false; + } + + @Override + public final int getTransferLimit(Object o, int transferSize) { + if (o instanceof ItemStack stack) { + return getTransferLimit(stack, transferSize); + } else if (o instanceof FluidStack stack) { + return getTransferLimit(stack, transferSize); + } + return 0; + } + + public int getTransferLimit(FluidStack stack, int transferSize) { + return 0; + } + + public int getTransferLimit(ItemStack stack, int transferSize) { + return 0; + } + + public final boolean isBlacklistFilter() { + return getFilterReader().isBlacklistFilter(); + } + + public IWidget createBlacklistUI() { + return new ParentWidget<>().coverChildren() + .child(new CycleButtonWidget() + .value(new BooleanSyncValue( + this::isBlacklistFilter, + this::setBlacklistFilter)) + .textureGetter(state -> GTGuiTextures.BUTTON_BLACKLIST[state]) + .addTooltip(0, IKey.lang("cover.filter.blacklist.disabled")) + .addTooltip(1, IKey.lang("cover.filter.blacklist.enabled"))); + } + + public final int getMaxTransferSize() { + return this.getFilterReader().getMaxTransferRate(); + } + + public final void setMaxTransferSize(int maxStackSize) { + this.getFilterReader().setMaxTransferRate(maxStackSize); + } + + public boolean showGlobalTransferLimitSlider() { + return isBlacklistFilter(); + } + + public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { + this.dirtyNotifiable = dirtyNotifiable; + this.getFilterReader().setDirtyNotifiable(dirtyNotifiable); + } + + public final void markDirty() { + if (dirtyNotifiable != null) { + dirtyNotifiable.markAsDirty(); + } + } + + public void readFromNBT(NBTTagCompound tag) { + this.getFilterReader().deserializeNBT(tag); + markDirty(); + } + + public void writeInitialSyncData(PacketBuffer packetBuffer) {} + + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) {} +} diff --git a/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java b/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java new file mode 100644 index 00000000000..489fd70659d --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java @@ -0,0 +1,273 @@ +package gregtech.common.covers.filter; + +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.PanelSyncHandler; +import com.cleanroommc.modularui.value.sync.SyncHandlers; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ItemSlot; +import com.cleanroommc.modularui.widgets.layout.Row; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +public abstract class BaseFilterContainer extends ItemStackHandler { + + private int maxTransferSize = 1; + private int transferSize; + private @Nullable BaseFilter currentFilter; + private @Nullable Runnable onFilterInstanceChange; + private final IDirtyNotifiable dirtyNotifiable; + + protected BaseFilterContainer(IDirtyNotifiable dirtyNotifiable) { + super(); + this.dirtyNotifiable = dirtyNotifiable; + } + + public boolean test(Object toTest) { + return !hasFilter() || getFilter().test(toTest); + } + + public MatchResult match(Object toMatch) { + if (!hasFilter()) + return MatchResult.create(true, toMatch, -1); + + return getFilter().match(toMatch); + } + + public int getTransferLimit(Object stack) { + if (!hasFilter() || isBlacklistFilter()) { + return getTransferSize(); + } + return getFilter().getTransferLimit(stack, getTransferSize()); + } + + @Override + public int getSlotLimit(int slot) { + return 1; + } + + public void onFilterInstanceChange() { + dirtyNotifiable.markAsDirty(); + if (onFilterInstanceChange != null) { + onFilterInstanceChange.run(); + } + } + + public void setOnFilterInstanceChange(@Nullable Runnable onFilterInstanceChange) { + this.onFilterInstanceChange = onFilterInstanceChange; + } + + public final @NotNull ItemStack getFilterStack() { + return this.getStackInSlot(0); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + if (ItemStack.areItemStacksEqual(stack, getFilterStack())) + return; + + if (stack.isEmpty()) { + setFilter(null); + } else if (isItemValid(stack)) { + setFilter(BaseFilter.getFilterFromStack(stack)); + } + + super.setStackInSlot(slot, stack); + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return isItemValid(stack); + } + + protected abstract boolean isItemValid(ItemStack stack); + + protected abstract String getFilterName(); + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + if (!isItemValid(stack)) return stack; + var remainder = super.insertItem(slot, stack, simulate); + if (!simulate) setFilter(BaseFilter.getFilterFromStack(stack)); + return remainder; + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + var extracted = super.extractItem(slot, amount, simulate); + if (!extracted.isEmpty()) { + setFilter(null); + } + return extracted; + } + + public final void setFilterStack(ItemStack stack) { + setStackInSlot(0, stack); + } + + public int getMaxTransferSize() { + return !showGlobalTransferLimitSlider() && hasFilter() ? currentFilter.getMaxTransferSize() : + this.maxTransferSize; + } + + public void setMaxTransferSize(int maxTransferSize) { + this.maxTransferSize = MathHelper.clamp(maxTransferSize, 1, Integer.MAX_VALUE); + this.transferSize = MathHelper.clamp(this.transferSize, 1, this.maxTransferSize); + if (hasFilter()) currentFilter.setMaxTransferSize(this.maxTransferSize); + } + + public final boolean hasFilter() { + return currentFilter != null; + } + + public final @Nullable BaseFilter getFilter() { + return currentFilter; + } + + public final void setFilter(@Nullable BaseFilter newFilter) { + this.currentFilter = newFilter; + if (hasFilter()) { + this.currentFilter.setDirtyNotifiable(this.dirtyNotifiable); + this.currentFilter.setMaxTransferSize(this.maxTransferSize); + } + if (onFilterInstanceChange != null) { + this.onFilterInstanceChange.run(); + } + } + + public boolean showGlobalTransferLimitSlider() { + return this.maxTransferSize > 0 && (!hasFilter() || getFilter().showGlobalTransferLimitSlider()); + } + + public void setBlacklistFilter(boolean blacklistFilter) { + if (hasFilter()) getFilter().setBlacklistFilter(blacklistFilter); + onFilterInstanceChange(); + } + + public final boolean isBlacklistFilter() { + return hasFilter() && getFilter().isBlacklistFilter(); + } + + public int getTransferSize() { + if (!showGlobalTransferLimitSlider()) { + return getMaxTransferSize(); + } + return this.transferSize; + } + + public int getTransferLimit(int slotIndex) { + if (isBlacklistFilter() || !hasFilter()) { + return getTransferSize(); + } + return this.currentFilter.getTransferLimit(slotIndex, getTransferSize()); + } + + public void setTransferSize(int transferSize) { + this.transferSize = MathHelper.clamp(transferSize, 1, getMaxTransferSize()); + onFilterInstanceChange(); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tagCompound = new NBTTagCompound(); + tagCompound.setTag("FilterInventory", super.serializeNBT()); + // tagCompound.setInteger("MaxStackSize", getMaxTransferSize()); + tagCompound.setInteger("TransferStackSize", getTransferSize()); + return tagCompound; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt.getCompoundTag("FilterInventory")); + setFilter(BaseFilter.getFilterFromStack(getFilterStack())); + if (nbt.hasKey("TransferStackSize")) + this.transferSize = nbt.getInteger("TransferStackSize"); + } + + public void handleLegacyNBT(NBTTagCompound nbt) { + if (hasFilter()) { + getFilter().getFilterReader().handleLegacyNBT(nbt); + } + } + + /** Uses Cleanroom MUI */ + public IWidget initUI(ModularPanel main, GuiSyncManager manager) { + var panel = new PanelSyncHandler(main) { + + // the panel can't be opened if there's no filter, so `getFilter()` should not be null + @Override + public ModularPanel createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var filter = hasFilter() ? getFilter() : BaseFilter.ERROR_FILTER; + filter.setMaxTransferSize(getMaxTransferSize()); + return filter.createPopupPanel(syncManager); + } + }; + + manager.syncValue("filter_panel", panel); + var filterButton = new ButtonWidget<>(); + filterButton.setEnabled(hasFilter()); + + return new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ItemSlot() + .slot(SyncHandlers.itemSlot(this, 0) + .filter(this::isItemValid) + .singletonSlotGroup(101) + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (!isItemValid(newItem) && panel.isPanelOpen()) { + panel.closePanel(); + } + })) + .size(18).marginRight(2) + .background(GTGuiTextures.SLOT, GTGuiTextures.FILTER_SLOT_OVERLAY.asIcon().size(16))) + .child(filterButton + .background(GTGuiTextures.MC_BUTTON, GTGuiTextures.FILTER_SETTINGS_OVERLAY.asIcon().size(16)) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, + GTGuiTextures.FILTER_SETTINGS_OVERLAY.asIcon().size(16)) + .setEnabledIf(w -> hasFilter()) + .onMousePressed(i -> { + if (!panel.isPanelOpen()) { + panel.openPanel(); + } else { + panel.closePanel(); + } + Interactable.playButtonClickSound(); + return true; + })) + .child(IKey.dynamic(this::getFilterName) + .alignment(Alignment.CenterRight).asWidget() + .left(36).right(0).height(18)); + } + + public void writeInitialSyncData(PacketBuffer packetBuffer) { + packetBuffer.writeItemStack(this.getFilterStack()); + packetBuffer.writeInt(this.maxTransferSize); + packetBuffer.writeInt(this.transferSize); + } + + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + var stack = ItemStack.EMPTY; + try { + stack = packetBuffer.readItemStack(); + } catch (IOException ignore) {} + this.setFilterStack(stack); + this.setMaxTransferSize(packetBuffer.readInt()); + this.setTransferSize(packetBuffer.readInt()); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java b/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java deleted file mode 100644 index 633242b05d2..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java +++ /dev/null @@ -1,103 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.unification.stack.ItemAndMetadata; -import gregtech.api.util.GTLog; -import gregtech.common.items.MetaItems; - -import net.minecraft.item.ItemStack; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - -import java.util.Map; - -public class FilterTypeRegistry { - - private static final Map itemFilterIdByStack = new Object2IntOpenHashMap<>(); - private static final Map fluidFilterIdByStack = new Object2IntOpenHashMap<>(); - private static final BiMap> itemFilterById = HashBiMap.create(); - private static final BiMap> fluidFilterById = HashBiMap.create(); - - public static void init() { - registerFluidFilter(1, SimpleFluidFilter.class, MetaItems.FLUID_FILTER.getStackForm()); - registerItemFilter(2, SimpleItemFilter.class, MetaItems.ITEM_FILTER.getStackForm()); - registerItemFilter(3, OreDictionaryItemFilter.class, MetaItems.ORE_DICTIONARY_FILTER.getStackForm()); - registerItemFilter(4, SmartItemFilter.class, MetaItems.SMART_FILTER.getStackForm()); - } - - public static void registerFluidFilter(int id, Class fluidFilterClass, ItemStack itemStack) { - if (fluidFilterById.containsKey(id)) { - throw new IllegalArgumentException("Id is already occupied: " + id); - } - fluidFilterIdByStack.put(new ItemAndMetadata(itemStack), id); - fluidFilterById.put(id, fluidFilterClass); - } - - public static void registerItemFilter(int id, Class itemFilterClass, ItemStack itemStack) { - if (itemFilterById.containsKey(id)) { - throw new IllegalArgumentException("Id is already occupied: " + id); - } - itemFilterIdByStack.put(new ItemAndMetadata(itemStack), id); - itemFilterById.put(id, itemFilterClass); - } - - public static int getIdForItemFilter(ItemFilter itemFilter) { - Integer filterId = itemFilterById.inverse().get(itemFilter.getClass()); - if (filterId == null) { - throw new IllegalArgumentException("Unknown filter type " + itemFilter.getClass()); - } - return filterId; - } - - public static int getIdForFluidFilter(FluidFilter fluidFilter) { - Integer filterId = fluidFilterById.inverse().get(fluidFilter.getClass()); - if (filterId == null) { - throw new IllegalArgumentException("Unknown filter type " + fluidFilter.getClass()); - } - return filterId; - } - - public static ItemFilter createItemFilterById(int filterId) { - Class filterClass = itemFilterById.get(filterId); - if (filterClass == null) { - throw new IllegalArgumentException("Unknown filter id: " + filterId); - } - return createNewFilterInstance(filterClass); - } - - public static FluidFilter createFluidFilterById(int filterId) { - Class filterClass = fluidFilterById.get(filterId); - if (filterClass == null) { - throw new IllegalArgumentException("Unknown filter id: " + filterId); - } - return createNewFilterInstance(filterClass); - } - - public static ItemFilter getItemFilterForStack(ItemStack itemStack) { - Integer filterId = itemFilterIdByStack.get(new ItemAndMetadata(itemStack)); - if (filterId == null) { - return null; - } - Class filterClass = itemFilterById.get(filterId); - return createNewFilterInstance(filterClass); - } - - public static FluidFilter getFluidFilterForStack(ItemStack itemStack) { - Integer filterId = fluidFilterIdByStack.get(new ItemAndMetadata(itemStack)); - if (filterId == null) { - return null; - } - Class filterClass = fluidFilterById.get(filterId); - return createNewFilterInstance(filterClass); - } - - private static T createNewFilterInstance(Class filterClass) { - try { - return filterClass.newInstance(); - } catch (ReflectiveOperationException exception) { - GTLog.logger.error("Failed to create filter instance for class {}", filterClass, exception); - return null; - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilter.java b/src/main/java/gregtech/common/covers/filter/FluidFilter.java deleted file mode 100644 index 6d6dc23254b..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FluidFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.Widget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; - -import java.util.function.Consumer; - -public abstract class FluidFilter { - - private IDirtyNotifiable dirtyNotifiable; - boolean showTip; - - public abstract boolean testFluid(FluidStack fluidStack); - - public abstract int getFluidTransferLimit(FluidStack fluidStack); - - public abstract int getMaxOccupiedHeight(); - - public abstract void initUI(Consumer widgetGroup); - - public abstract void writeToNBT(NBTTagCompound tagCompound); - - public abstract void readFromNBT(NBTTagCompound tagCompound); - - public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public abstract void configureFilterTanks(int amount); - - public abstract void setMaxConfigurableFluidSize(int maxStackSize); - - public final void markDirty() { - if (dirtyNotifiable != null) { - dirtyNotifiable.markAsDirty(); - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java index 41beb67b6d6..a3793c0ffed 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java @@ -1,128 +1,64 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.util.IDirtyNotifiable; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.items.ItemStackHandler; -import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; +import org.jetbrains.annotations.ApiStatus; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; -import java.util.function.Supplier; -public class FluidFilterContainer implements INBTSerializable { - - private final ItemStackHandler filterInventory; - private final FluidFilterWrapper filterWrapper; - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, int capacity) { - this.filterWrapper = new FluidFilterWrapper(dirtyNotifiable, capacity); - this.filterInventory = new ItemStackHandler(1) { - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return FilterTypeRegistry.getFluidFilterForStack(stack) != null; - } - - @Override - public int getSlotLimit(int slot) { - return 1; - } - - @Override - protected void onLoad() { - onFilterSlotChange(false); - } - - @Override - protected void onContentsChanged(int slot) { - onFilterSlotChange(true); - } - }; - } - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, Supplier showTip, int maxSize) { - this(dirtyNotifiable, maxSize); - filterWrapper.setTipSupplier(showTip); - } - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, Supplier showTip) { - this(dirtyNotifiable, 1000); - filterWrapper.setTipSupplier(showTip); - } +public class FluidFilterContainer extends BaseFilterContainer { public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable) { - this(dirtyNotifiable, 1000); - filterWrapper.setTipSupplier(() -> false); - } - - public ItemStackHandler getFilterInventory() { - return filterInventory; - } - - public FluidFilterWrapper getFilterWrapper() { - return filterWrapper; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.pump.fluid_filter.title")); - widgetGroup.accept(new SlotWidget(filterInventory, 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - this.filterWrapper.initUI(y + 15, widgetGroup); - this.filterWrapper.blacklistUI(y + 15, widgetGroup, () -> true); + super(dirtyNotifiable); } - protected void onFilterSlotChange(boolean notify) { - ItemStack filterStack = filterInventory.getStackInSlot(0); - FluidFilter newFluidFilter = FilterTypeRegistry.getFluidFilterForStack(filterStack); - FluidFilter currentFluidFilter = filterWrapper.getFluidFilter(); - if (newFluidFilter == null) { - if (currentFluidFilter != null) { - filterWrapper.setFluidFilter(null); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } else if (currentFluidFilter == null || - newFluidFilter.getClass() != currentFluidFilter.getClass()) { - filterWrapper.setFluidFilter(newFluidFilter); - if (notify) filterWrapper.onFilterInstanceChange(); - } + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new gregtech.api.gui.widgets.LabelWidget(10, y, "cover.pump.fluid_filter.title")); + widgetGroup.accept(new gregtech.api.gui.widgets.SlotWidget(this, 0, 10, y + 15) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT, + gregtech.api.gui.GuiTextures.FILTER_SLOT_OVERLAY)); + + this.initFilterUI(y + 15, widgetGroup); + this.blacklistUI(y + 15, widgetGroup, () -> true); } - public boolean testFluidStack(FluidStack fluidStack) { - return filterWrapper.testFluidStack(fluidStack); + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initFilterUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new WidgetGroupFluidFilter(y, this::getFilter, this::showGlobalTransferLimitSlider)); } - public boolean testFluidStack(FluidStack fluidStack, Boolean whitelist) { - return filterWrapper.testFluidStack(fluidStack, whitelist); + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { + gregtech.api.gui.widgets.ServerWidgetGroup blacklistButton = new gregtech.api.gui.widgets.ServerWidgetGroup( + this::hasFilter); + blacklistButton.addWidget(new gregtech.api.gui.widgets.ToggleButtonWidget(144, y, 18, 18, + gregtech.api.gui.GuiTextures.BUTTON_BLACKLIST, + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + .setTooltipText("cover.filter.blacklist")); + widgetGroup.accept(blacklistButton); } @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tagCompound = new NBTTagCompound(); - tagCompound.setTag("FilterInventory", filterInventory.serializeNBT()); - tagCompound.setBoolean("IsBlacklist", filterWrapper.isBlacklistFilter()); - if (filterWrapper.getFluidFilter() != null) { - NBTTagCompound filterInventory = new NBTTagCompound(); - filterWrapper.getFluidFilter().writeToNBT(filterInventory); - tagCompound.setTag("Filter", filterInventory); - } - return tagCompound; + protected boolean isItemValid(ItemStack stack) { + var filter = BaseFilter.getFilterFromStack(stack); + return filter != null && filter.getType() == IFilter.FilterType.FLUID; } @Override - public void deserializeNBT(NBTTagCompound tagCompound) { - this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - if (filterWrapper.getFluidFilter() != null) { - this.filterWrapper.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); - } + protected String getFilterName() { + return hasFilter() ? + getFilterStack().getDisplayName() : + IKey.lang("metaitem.fluid_filter.name").get(); } } diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java deleted file mode 100644 index 2ef1f76a32e..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java +++ /dev/null @@ -1,98 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.ServerWidgetGroup; -import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraftforge.fluids.FluidStack; - -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class FluidFilterWrapper { - - private final IDirtyNotifiable dirtyNotifiable; - private boolean isBlacklistFilter = false; - private FluidFilter currentFluidFilter; - private Supplier showTipSupplier; - private int maxSize = 1000; - - public FluidFilterWrapper(IDirtyNotifiable dirtyNotifiable, int maxSize) { - this.dirtyNotifiable = dirtyNotifiable; - this.maxSize = maxSize; - } - - public FluidFilterWrapper(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new WidgetGroupFluidFilter(y, this::getFluidFilter, shouldShowTip())); - } - - public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { - ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getFluidFilter() != null); - blacklistButton.addWidget(new ToggleButtonWidget(144, y, 18, 18, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) - .setTooltipText("cover.filter.blacklist")); - widgetGroup.accept(blacklistButton); - } - - public void setFluidFilter(FluidFilter fluidFilter) { - this.currentFluidFilter = fluidFilter; - if (currentFluidFilter != null) { - currentFluidFilter.setDirtyNotifiable(dirtyNotifiable); - currentFluidFilter.setMaxConfigurableFluidSize(maxSize); - } - } - - private Supplier shouldShowTip() { - return showTipSupplier; - } - - protected void setTipSupplier(Supplier supplier) { - this.showTipSupplier = supplier; - } - - public FluidFilter getFluidFilter() { - return currentFluidFilter; - } - - public void onFilterInstanceChange() { - dirtyNotifiable.markAsDirty(); - } - - public void setBlacklistFilter(boolean blacklistFilter) { - isBlacklistFilter = blacklistFilter; - dirtyNotifiable.markAsDirty(); - } - - public boolean isBlacklistFilter() { - return isBlacklistFilter; - } - - public boolean testFluidStack(FluidStack fluidStack, boolean whitelist) { - boolean result = true; - if (currentFluidFilter != null) { - result = currentFluidFilter.testFluid(fluidStack); - } - if (!whitelist) { - result = !result; - } - return result; - } - - public boolean testFluidStack(FluidStack fluidStack) { - boolean result = true; - if (currentFluidFilter != null) { - result = currentFluidFilter.testFluid(fluidStack); - } - if (isBlacklistFilter) { - result = !result; - } - return result; - } -} diff --git a/src/main/java/gregtech/common/covers/filter/IFilter.java b/src/main/java/gregtech/common/covers/filter/IFilter.java new file mode 100644 index 00000000000..06345143982 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/IFilter.java @@ -0,0 +1,77 @@ +package gregtech.common.covers.filter; + +import gregtech.api.items.metaitem.stats.IItemComponent; +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public interface IFilter { + + @Deprecated + default void initUI(Consumer widgetGroup) {} + + /** Uses Cleanroom MUI */ + @NotNull + ModularPanel createPopupPanel(GuiSyncManager syncManager); + + /** Uses Cleanroom MUI */ + @NotNull + ModularPanel createPanel(GuiSyncManager syncManager); + + /** Uses Cleanroom MUI - Creates the widgets standalone so that they can be put into their own panel */ + + @NotNull + Widget createWidgets(GuiSyncManager syncManager); + + ItemStack getContainerStack(); + + void setDirtyNotifiable(@Nullable IDirtyNotifiable dirtyNotifiable); + + void markDirty(); + + int getMaxTransferSize(); + + void setMaxTransferSize(int maxTransferSize); + + boolean showGlobalTransferLimitSlider(); + + MatchResult match(Object toMatch); + + boolean test(Object toTest); + + int getTransferLimit(Object stack, int transferSize); + + default int getTransferLimit(int slot, int transferSize) { + return transferSize; + } + + void readFromNBT(NBTTagCompound tagCompound); + + FilterType getType(); + + enum FilterType { + ITEM, + FLUID + } + + // this only exists so i can pass in the constructor reference as a metaitem componant + static Factory factory(Factory factory) { + return factory; + } + + @FunctionalInterface + interface Factory extends IItemComponent { + + @NotNull + BaseFilter create(@NotNull ItemStack stack); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilter.java b/src/main/java/gregtech/common/covers/filter/ItemFilter.java deleted file mode 100644 index a5b350da33d..00000000000 --- a/src/main/java/gregtech/common/covers/filter/ItemFilter.java +++ /dev/null @@ -1,50 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.Widget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; - -import java.util.function.Consumer; - -public abstract class ItemFilter { - - private IDirtyNotifiable dirtyNotifiable; - private int maxStackSize = Integer.MAX_VALUE; - - public final int getMaxStackSize() { - return maxStackSize; - } - - public final void setMaxStackSize(int maxStackSize) { - this.maxStackSize = maxStackSize; - onMaxStackSizeChange(); - } - - protected void onMaxStackSizeChange() {} - - public abstract boolean showGlobalTransferLimitSlider(); - - public abstract int getSlotTransferLimit(Object matchSlot, int globalTransferLimit); - - public abstract Object matchItemStack(ItemStack itemStack); - - public abstract int getTotalOccupiedHeight(); - - public abstract void initUI(Consumer widgetGroup); - - public abstract void writeToNBT(NBTTagCompound tagCompound); - - public abstract void readFromNBT(NBTTagCompound tagCompound); - - final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public final void markDirty() { - if (dirtyNotifiable != null) { - dirtyNotifiable.markAsDirty(); - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java index 71be9ff14d3..d282595253d 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java @@ -1,165 +1,65 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.ServerWidgetGroup; import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.gui.widgets.ToggleButtonWidget; import gregtech.api.util.IDirtyNotifiable; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.items.ItemStackHandler; -import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; +import org.jetbrains.annotations.ApiStatus; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; -public class ItemFilterContainer implements INBTSerializable { - - private final ItemStackHandler filterInventory; - private final ItemFilterWrapper filterWrapper; - private int maxStackSizeLimit = 1; - private int transferStackSize; +public class ItemFilterContainer extends BaseFilterContainer { public ItemFilterContainer(IDirtyNotifiable dirtyNotifiable) { - this.filterWrapper = new ItemFilterWrapper(dirtyNotifiable); - this.filterWrapper.setOnFilterInstanceChange(this::onFilterInstanceChange); - this.filterInventory = new ItemStackHandler(1) { - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return FilterTypeRegistry.getItemFilterForStack(stack) != null; - } - - @Override - public int getSlotLimit(int slot) { - return 1; - } - - @Override - protected void onLoad() { - onFilterSlotChange(false); - } - - @Override - protected void onContentsChanged(int slot) { - onFilterSlotChange(true); - } - }; - } - - public ItemStackHandler getFilterInventory() { - return filterInventory; - } - - public ItemFilterWrapper getFilterWrapper() { - return filterWrapper; - } - - private void onFilterInstanceChange() { - this.filterWrapper.setMaxStackSize(getTransferStackSize()); - } - - public int getMaxStackSize() { - return maxStackSizeLimit; - } - - public int getTransferStackSize() { - if (!showGlobalTransferLimitSlider()) { - return getMaxStackSize(); - } - return transferStackSize; + super(dirtyNotifiable); } - public void setTransferStackSize(int transferStackSize) { - this.transferStackSize = MathHelper.clamp(transferStackSize, 1, getMaxStackSize()); - this.filterWrapper.setMaxStackSize(getTransferStackSize()); - } - - public void adjustTransferStackSize(int amount) { - setTransferStackSize(transferStackSize + amount); - } - - public void initUI(int y, Consumer widgetGroup) { + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initUI(int y, Consumer widgetGroup) { widgetGroup.accept(new LabelWidget(10, y, "cover.conveyor.item_filter.title")); - widgetGroup.accept(new SlotWidget(filterInventory, 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - this.filterWrapper.initUI(y + 38, widgetGroup); - this.filterWrapper.blacklistUI(y + 38, widgetGroup, () -> true); - } - - protected void onFilterSlotChange(boolean notify) { - ItemStack filterStack = filterInventory.getStackInSlot(0); - ItemFilter newItemFilter = FilterTypeRegistry.getItemFilterForStack(filterStack); - ItemFilter currentItemFilter = filterWrapper.getItemFilter(); - if (newItemFilter == null) { - if (currentItemFilter != null) { - filterWrapper.setItemFilter(null); - filterWrapper.setBlacklistFilter(false); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } else if (currentItemFilter == null || - newItemFilter.getClass() != currentItemFilter.getClass()) { - filterWrapper.setItemFilter(newItemFilter); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } - - public void setMaxStackSize(int maxStackSizeLimit) { - this.maxStackSizeLimit = maxStackSizeLimit; - setTransferStackSize(transferStackSize); - } - - public boolean showGlobalTransferLimitSlider() { - return getMaxStackSize() > 1 && filterWrapper.showGlobalTransferLimitSlider(); - } - - public int getSlotTransferLimit(Object slotIndex) { - return filterWrapper.getSlotTransferLimit(slotIndex, getTransferStackSize()); - } - - public Object matchItemStack(ItemStack itemStack) { - return filterWrapper.matchItemStack(itemStack); - } + widgetGroup.accept(new SlotWidget(this, 0, 10, y + 15) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT, + gregtech.api.gui.GuiTextures.FILTER_SLOT_OVERLAY)); - public Object matchItemStack(ItemStack itemStack, boolean whitelist) { - return filterWrapper.matchItemStack(itemStack, whitelist); + this.initFilterUI(y + 38, widgetGroup); } - public boolean testItemStack(ItemStack itemStack) { - return matchItemStack(itemStack) != null; + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initFilterUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new WidgetGroupItemFilter(y, this::getFilter)); } - public boolean testItemStack(ItemStack itemStack, boolean whitelist) { - return matchItemStack(itemStack, whitelist) != null; + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { + ServerWidgetGroup blacklistButton = new ServerWidgetGroup(this::hasFilter); + blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, gregtech.api.gui.GuiTextures.BUTTON_BLACKLIST, + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + .setTooltipText("cover.filter.blacklist")); + widgetGroup.accept(blacklistButton); } @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tagCompound = new NBTTagCompound(); - tagCompound.setTag("FilterInventory", filterInventory.serializeNBT()); - tagCompound.setBoolean("IsBlacklist", filterWrapper.isBlacklistFilter()); - tagCompound.setInteger("MaxStackSize", maxStackSizeLimit); - tagCompound.setInteger("TransferStackSize", transferStackSize); - if (filterWrapper.getItemFilter() != null) { - NBTTagCompound filterInventory = new NBTTagCompound(); - filterWrapper.getItemFilter().writeToNBT(filterInventory); - tagCompound.setTag("Filter", filterInventory); - } - return tagCompound; + protected boolean isItemValid(ItemStack stack) { + var filter = BaseFilter.getFilterFromStack(stack); + return filter != null && filter.getType() == IFilter.FilterType.ITEM; } @Override - public void deserializeNBT(NBTTagCompound tagCompound) { - this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - setMaxStackSize(tagCompound.getInteger("MaxStackSize")); - setTransferStackSize(tagCompound.getInteger("TransferStackSize")); - if (filterWrapper.getItemFilter() != null) { - this.filterWrapper.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); - } + protected String getFilterName() { + return hasFilter() ? + getFilterStack().getDisplayName() : + IKey.lang("metaitem.item_filter.name").get(); } } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java deleted file mode 100644 index d11905e00b5..00000000000 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java +++ /dev/null @@ -1,132 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.ServerWidgetGroup; -import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.item.ItemStack; - -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; - -public class ItemFilterWrapper { - - private static final Object MATCH_RESULT_TRUE = new Object(); - private final IDirtyNotifiable dirtyNotifiable; - private boolean isBlacklistFilter = false; - private int maxStackSize = 1; - private ItemFilter currentItemFilter; - private Runnable onFilterInstanceChange; - - public ItemFilterWrapper(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new WidgetGroupItemFilter(y, this::getItemFilter)); - } - - public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { - ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getItemFilter() != null); - blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) - .setTooltipText("cover.filter.blacklist")); - widgetGroup.accept(blacklistButton); - } - - public void setItemFilter(ItemFilter itemFilter) { - this.currentItemFilter = itemFilter; - if (currentItemFilter != null) { - currentItemFilter.setDirtyNotifiable(dirtyNotifiable); - } - if (onFilterInstanceChange != null) { - this.onFilterInstanceChange.run(); - } - } - - public ItemFilter getItemFilter() { - return currentItemFilter; - } - - public void setOnFilterInstanceChange(Runnable onFilterInstanceChange) { - this.onFilterInstanceChange = onFilterInstanceChange; - } - - public void onFilterInstanceChange() { - if (currentItemFilter != null) { - currentItemFilter.setMaxStackSize(getInternalMaxStackSize()); - } - dirtyNotifiable.markAsDirty(); - } - - public void setMaxStackSize(int maxStackSize) { - this.maxStackSize = maxStackSize; - onFilterInstanceChange(); - dirtyNotifiable.markAsDirty(); - } - - public void setBlacklistFilter(boolean blacklistFilter) { - isBlacklistFilter = blacklistFilter; - onFilterInstanceChange(); - dirtyNotifiable.markAsDirty(); - } - - public boolean isBlacklistFilter() { - return isBlacklistFilter; - } - - public int getMaxStackSize() { - return maxStackSize; - } - - private int getInternalMaxStackSize() { - if (isBlacklistFilter()) { - return 1; - } else { - return getMaxStackSize(); - } - } - - public boolean showGlobalTransferLimitSlider() { - return isBlacklistFilter() || currentItemFilter == null || currentItemFilter.showGlobalTransferLimitSlider(); - } - - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - if (isBlacklistFilter() || currentItemFilter == null) { - return globalTransferLimit; - } - return currentItemFilter.getSlotTransferLimit(matchSlot, globalTransferLimit); - } - - public Object matchItemStack(ItemStack itemStack) { - Object originalResult; - if (currentItemFilter == null) { - originalResult = MATCH_RESULT_TRUE; - } else { - originalResult = currentItemFilter.matchItemStack(itemStack); - } - if (isBlacklistFilter()) { - originalResult = originalResult == null ? MATCH_RESULT_TRUE : null; - } - return originalResult; - } - - public Object matchItemStack(ItemStack itemStack, boolean whitelist) { - Object originalResult; - if (currentItemFilter == null) { - originalResult = MATCH_RESULT_TRUE; - } else { - originalResult = currentItemFilter.matchItemStack(itemStack); - } - if (!whitelist) { - originalResult = originalResult == null ? MATCH_RESULT_TRUE : null; - } - return originalResult; - } - - public boolean testItemStack(ItemStack itemStack) { - return matchItemStack(itemStack) != null; - } -} diff --git a/src/main/java/gregtech/common/covers/filter/MatchResult.java b/src/main/java/gregtech/common/covers/filter/MatchResult.java new file mode 100644 index 00000000000..028da359cb3 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/MatchResult.java @@ -0,0 +1,46 @@ +package gregtech.common.covers.filter; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class MatchResult { + + public static final MatchResult NONE = new MatchResult(false, null, -1); + public static final MatchResult ANY = new MatchResult(true, null, -1); + private final boolean matched; + private final Object matchedObject; + private final int filterIndex; + + private MatchResult(boolean matched, Object matchedObject, int filterIndex) { + this.matched = matched; + this.matchedObject = matchedObject; + this.filterIndex = filterIndex; + } + + public boolean isMatched() { + return matched; + } + + public Object getMatchedObject() { + return matchedObject; + } + + public @NotNull ItemStack getItemStack() { + return matchedObject instanceof ItemStack stack ? stack : ItemStack.EMPTY; + } + + public @Nullable FluidStack getFluidStack() { + return matchedObject instanceof FluidStack stack ? stack : null; + } + + public int getFilterIndex() { + return filterIndex; + } + + public static MatchResult create(boolean matched, Object matchedStack, int filterIndex) { + return new MatchResult(matched, matchedStack, filterIndex); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java index 1db9a6087e3..2a9fcaf402d 100644 --- a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java @@ -1,78 +1,69 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.DrawableWidget; -import gregtech.api.gui.widgets.ImageCycleButtonWidget; -import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.cover.CoverWithUI; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.stack.ItemVariantMap; import gregtech.api.unification.stack.MultiItemVariantMap; import gregtech.api.unification.stack.SingleItemVariantMap; -import gregtech.api.util.function.BooleanConsumer; -import gregtech.api.util.oreglob.OreGlob; import gregtech.api.util.oreglob.OreGlobCompileResult; -import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; -import gregtech.common.gui.widget.HighlightedTextField; -import gregtech.common.gui.widget.orefilter.ItemOreFilterTestSlot; -import gregtech.common.gui.widget.orefilter.OreGlobCompileStatusWidget; +import gregtech.common.covers.filter.readers.OreDictFilterReader; +import gregtech.common.mui.widget.HighlightedTextField; +import gregtech.common.mui.widget.orefilter.OreFilterTestSlot; +import net.minecraft.client.resources.I18n; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; import net.minecraft.util.text.TextFormatting; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.Tooltip; +import com.cleanroommc.modularui.utils.BooleanConsumer; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.BooleanSupplier; import java.util.function.Consumer; -public class OreDictionaryItemFilter extends ItemFilter { +public class OreDictionaryItemFilter extends BaseFilter { private final Map> matchCache = new Object2ObjectOpenHashMap<>(); private final SingleItemVariantMap noOreDictMatch = new SingleItemVariantMap<>(); + private final OreDictFilterReader filterReader; - protected String expression = ""; - - private OreGlob glob = ImpossibleOreGlob.getInstance(); - private boolean error; - - private boolean caseSensitive; - /** - * {@code false} requires any of the entry to be match in order for the match to be success, {@code true} requires - * all entries to match - */ - private boolean matchAll; + public OreDictionaryItemFilter(ItemStack stack) { + this.filterReader = new OreDictFilterReader(stack); + recompile(); + } - @NotNull - public String getExpression() { - return expression; + @Override + public OreDictFilterReader getFilterReader() { + return filterReader; } @NotNull - public OreGlob getGlob() { - return this.glob; + public String getExpression() { + return this.filterReader.getExpression(); } - protected void recompile(@Nullable Consumer<@Nullable OreGlobCompileResult> callback) { + protected void recompile() { clearCache(); - String expr = this.expression; - if (!expr.isEmpty()) { - OreGlobCompileResult result = OreGlob.compile(expr, !this.caseSensitive); - this.glob = result.getInstance(); - this.error = result.hasError(); - if (callback != null) callback.accept(result); - } else { - this.glob = ImpossibleOreGlob.getInstance(); - this.error = true; - if (callback != null) callback.accept(null); - } + this.filterReader.recompile(); } protected void clearCache() { @@ -81,106 +72,211 @@ protected void clearCache() { } @Override - public void initUI(Consumer widgetGroup) { - ItemOreFilterTestSlot[] testSlot = new ItemOreFilterTestSlot[5]; - for (int i = 0; i < testSlot.length; i++) { - ItemOreFilterTestSlot slot = new ItemOreFilterTestSlot(20 + 22 * i, 0); - slot.setGlob(getGlob()); - slot.setMatchAll(this.matchAll); - widgetGroup.accept(slot); - testSlot[i] = slot; - } - OreGlobCompileStatusWidget compilationStatus = new OreGlobCompileStatusWidget(10, 10); + public void initUI(Consumer widgetGroup) {} - Consumer<@Nullable OreGlobCompileResult> compileCallback = result -> { - compilationStatus.setCompileResult(result); - for (ItemOreFilterTestSlot slot : testSlot) { - slot.setGlob(getGlob()); + @Override + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("ore_dict_filter", 188, 76) + .padding(7) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22)); + } + + @Override + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("ore_dict_filter", 100, 100); + } + + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + List oreSlots = new ArrayList<>(); + var expression = new StringSyncValue(this.filterReader::getExpression, this.filterReader::setExpression); + + BooleanConsumer setCaseSensitive = b -> { + this.filterReader.setCaseSensitive(b); + if (!syncManager.isClient()) return; + for (var slot : oreSlots) { + slot.updatePreview(); } }; - HighlightedTextField textField = new HighlightedTextField(14, 26, 152, 14, () -> this.expression, - s -> { - if (s.equals(this.expression)) return; - this.expression = s; - markDirty(); - recompile(compileCallback); - }); - compilationStatus.setTextField(textField); - - widgetGroup.accept(new ImageWidget(10, 0, 7, 7, GuiTextures.ORE_FILTER_INFO) - .setTooltip("cover.ore_dictionary_filter.info")); - widgetGroup.accept(compilationStatus); - widgetGroup.accept(new DrawableWidget(10, 22, 156, 16) - .setBackgroundDrawer((mouseX, mouseY, partialTicks, context, widget) -> { - Widget.drawGradientRect(widget.getPosition().x, widget.getPosition().y, - widget.getSize().width, widget.getSize().height, - 0xFF808080, 0xFF808080, false); - Widget.drawGradientRect(widget.getPosition().x + 1, widget.getPosition().y + 1, - widget.getSize().width - 2, widget.getSize().height - 2, - 0xFF000000, 0xFF000000, false); - })); - widgetGroup.accept(textField - .setHighlightRule(h -> { - String t = h.getOriginalText(); - for (int i = 0; i < t.length(); i++) { - switch (t.charAt(i)) { - case '|', '&', '^', '(', ')' -> h.format(i, TextFormatting.GOLD); - case '*', '?' -> h.format(i, TextFormatting.GREEN); - case '!' -> h.format(i, TextFormatting.RED); - case '\\' -> h.format(i++, TextFormatting.YELLOW); - case '$' -> { // TODO: remove this switch case in 2.9 - h.format(i, TextFormatting.DARK_GREEN); - for (; i < t.length(); i++) { - switch (t.charAt(i)) { - case ' ', '\t', '\n', '\r' -> {} - case '\\' -> { - i++; - continue; - } - default -> { - continue; - } - } - break; - } + BooleanConsumer setMatchAll = b -> { + this.clearCache(); + this.filterReader.setMatchAll(b); + if (!syncManager.isClient()) return; + for (var slot : oreSlots) { + slot.setMatchAll(b); + } + }; + + var caseSensitive = new BooleanSyncValue(this.filterReader::isCaseSensitive, setCaseSensitive); + var matchAll = new BooleanSyncValue(this.filterReader::shouldMatchAll, setMatchAll); + + return new Column().widthRel(1f).coverChildrenHeight() + .child(new HighlightedTextField() + .setHighlightRule(this::highlightRule) + .onUnfocus(() -> { + for (var slot : oreSlots) { + slot.updatePreview(); + } + }) + .setTextColor(Color.WHITE.darker(1)) + .value(expression).marginBottom(4) + .height(18).widthRel(1f)) + .child(new Row().coverChildrenHeight() + .widthRel(1f) + .child(new Column().height(18) + .coverChildrenWidth().marginRight(2) + .child(GTGuiTextures.OREDICT_INFO.asWidget() + .size(8).top(0) + .addTooltipLine(IKey.lang("cover.ore_dictionary_filter.info"))) + .child(new Widget<>() + .size(8).bottom(0) + .onUpdateListener(this::getStatusIcon) + .tooltipBuilder(this::createStatusTooltip) + .tooltip(tooltip -> tooltip.setAutoUpdate(true)))) + .child(SlotGroupWidget.builder() + .row("XXXXX") + .key('X', i -> { + var slot = new OreFilterTestSlot() + .setGlobSupplier(this.filterReader::getGlob); + slot.setMatchAll(this.filterReader.shouldMatchAll()); + oreSlots.add(slot); + return slot; + }) + .build().marginRight(2)) + .child(new CycleButtonWidget() + .size(18).value(caseSensitive) + .marginRight(2) + .textureGetter(state -> GTGuiTextures.BUTTON_CASE_SENSITIVE[state]) + .addTooltip(0, + IKey.lang("cover.ore_dictionary_filter.button.case_sensitive.disabled")) + .addTooltip(1, + IKey.lang("cover.ore_dictionary_filter.button.case_sensitive.enabled"))) + .child(new CycleButtonWidget() + .size(18).value(matchAll) + .marginRight(2) + .textureGetter(state -> GTGuiTextures.BUTTON_MATCH_ALL[state]) + .addTooltip(0, + IKey.lang("cover.ore_dictionary_filter.button.match_all.disabled")) + .addTooltip(1, + IKey.lang("cover.ore_dictionary_filter.button.match_all.enabled"))) + .child(createBlacklistUI())); + } + + protected void getStatusIcon(Widget widget) { + UITexture texture; + var result = this.filterReader.getResult(); + + if (result == null) { + texture = GTGuiTextures.OREDICT_WAITING; + } else if (result.getReports().length == 0) { + texture = GTGuiTextures.OREDICT_SUCCESS; + } else if (result.hasError()) { + texture = GTGuiTextures.OREDICT_ERROR; + } else { + texture = GTGuiTextures.OREDICT_WARN; + } + widget.background(texture); + } + + protected void createStatusTooltip(Tooltip tooltip) { + var result = this.filterReader.getResult(); + if (result == null) return; + List list = new ArrayList<>(); + + int error = 0, warn = 0; + for (OreGlobCompileResult.Report report : result.getReports()) { + if (report.isError()) error++; + else warn++; + list.add((report.isError() ? TextFormatting.RED : TextFormatting.GOLD) + report.toString()); + } + if (error > 0) { + if (warn > 0) { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.err_warn", error, warn)); + } else { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.err", error)); + } + } else { + if (warn > 0) { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.warn", warn)); + } else { + list.add(I18n.format("cover.ore_dictionary_filter.status.no_issues")); + } + list.add(""); + list.add(I18n.format("cover.ore_dictionary_filter.status.explain")); + list.add(""); + list.addAll(result.getInstance().toFormattedString()); + } + tooltip.addStringLines(list); + } + + protected String highlightRule(String text) { + StringBuilder builder = new StringBuilder(text); + for (int i = 0; i < builder.length(); i++) { + switch (builder.charAt(i)) { + case '|', '&', '^', '(', ')' -> { + builder.insert(i, TextFormatting.GOLD); + i += 2; + } + case '*', '?' -> { + builder.insert(i, TextFormatting.GREEN); + i += 2; + } + case '!' -> { + builder.insert(i, TextFormatting.RED); + i += 2; + } + case '\\' -> { + builder.insert(i++, TextFormatting.YELLOW); + i += 2; + } + case '$' -> { // TODO: remove this switch case in 2.9 + builder.insert(i, TextFormatting.DARK_GREEN); + for (; i < builder.length(); i++) { + switch (builder.charAt(i)) { + case ' ', '\t', '\n', '\r' -> {} + case '\\' -> { + i++; + continue; } default -> { continue; } } - h.format(i + 1, TextFormatting.RESET); - } - }).setMaxLength(64)); - widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(130, 38, 18, 18, - GuiTextures.ORE_FILTER_BUTTON_CASE_SENSITIVE, () -> this.caseSensitive, caseSensitive -> { - if (this.caseSensitive == caseSensitive) return; - this.caseSensitive = caseSensitive; - markDirty(); - recompile(compileCallback); - }).setTooltipHoverString( - i -> "cover.ore_dictionary_filter.button.case_sensitive." + (i == 0 ? "disabled" : "enabled"))); - widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(148, 38, 18, 18, - GuiTextures.ORE_FILTER_BUTTON_MATCH_ALL, () -> this.matchAll, matchAll -> { - if (this.matchAll == matchAll) return; - this.matchAll = matchAll; - markDirty(); - clearCache(); - for (ItemOreFilterTestSlot slot : testSlot) { - slot.setMatchAll(matchAll); + break; } - }).setTooltipHoverString( - i -> "cover.ore_dictionary_filter.button.match_all." + (i == 0 ? "disabled" : "enabled"))); + } + default -> { + continue; + } + } + builder.insert(i + 1, TextFormatting.RESET); + } + return builder.toString(); + } + + @Override + public MatchResult matchItem(ItemStack itemStack) { + // "wtf is this system?? i can put any non null object here and it i will work??? $arch" + // not anymore :thanosdaddy: -ghzdude + var match = matchesItemStack(itemStack); + return MatchResult.create(match != isBlacklistFilter(), match ? itemStack.copy() : ItemStack.EMPTY, -1); + } + + @Override + public boolean testItem(ItemStack toTest) { + return matchesItemStack(toTest); } @Override - public Object matchItemStack(ItemStack itemStack) { - return matchesItemStack(itemStack) ? - "wtf is this system?? i can put any non null object here and it i will work??? $arch" : null; + public FilterType getType() { + return FilterType.ITEM; } public boolean matchesItemStack(@NotNull ItemStack itemStack) { - if (this.error) return false; + var result = this.filterReader.getResult(); + if (result == null || result.hasError()) return false; Item item = itemStack.getItem(); ItemVariantMap> oreDictEntry = OreDictUnifier.getOreDictionaryEntry(item); @@ -188,7 +284,7 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { // no oredict entries associated Boolean cached = this.noOreDictMatch.getEntry(); if (cached == null) { - cached = this.glob.matches(""); + cached = this.filterReader.getGlob().matches(""); } this.matchCache.put(item, this.noOreDictMatch); return cached; @@ -205,7 +301,7 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { // no oredict entries associated Boolean cached = this.noOreDictMatch.getEntry(); if (cached == null) { - cached = this.glob.matches(""); + cached = this.filterReader.getGlob().matches(""); this.noOreDictMatch.put(cached); } this.matchCache.put(item, this.noOreDictMatch); @@ -217,64 +313,15 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { } this.matchCache.put(item, cacheEntry); } - boolean matches = this.matchAll ? this.glob.matchesAll(itemStack) : this.glob.matchesAny(itemStack); + boolean matches = this.filterReader.shouldMatchAll() ? + this.filterReader.getGlob().matchesAll(itemStack) : + this.filterReader.getGlob().matchesAny(itemStack); cacheEntry.put(itemStack, matches); return matches; } - @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - return globalTransferLimit; - } - @Override public boolean showGlobalTransferLimitSlider() { return true; } - - @Override - public int getTotalOccupiedHeight() { - return 37; - } - - @Override - public void writeToNBT(NBTTagCompound tag) { - tag.setString("OreDictionaryFilter", expression); - if (this.caseSensitive) tag.setBoolean("caseSensitive", true); - if (this.matchAll) tag.setBoolean("matchAll", true); - } - - @Override - public void readFromNBT(NBTTagCompound tag) { - this.expression = tag.getString("OreDictionaryFilter"); - this.caseSensitive = tag.getBoolean("caseSensitive"); - this.matchAll = tag.getBoolean("matchAll"); - recompile(null); - } - - public static class ForcedInitialSyncImageCycleButtonWidget extends ImageCycleButtonWidget { - - private final BooleanConsumer updater; - - public ForcedInitialSyncImageCycleButtonWidget(int xPosition, int yPosition, int width, int height, - TextureArea buttonTexture, BooleanSupplier supplier, - BooleanConsumer updater) { - super(xPosition, yPosition, width, height, buttonTexture, supplier, updater); - this.currentOption = 0; - this.updater = updater; - } - - @Override - public void readUpdateInfo(int id, PacketBuffer buffer) { - if (id == 1) { - int currentOptionCache = this.currentOption; - super.readUpdateInfo(id, buffer); - if (this.currentOption != currentOptionCache) { - this.updater.apply(currentOption >= 1); // call updater to apply necessary state changes - } - } else { - super.readUpdateInfo(id, buffer); - } - } - } } diff --git a/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java b/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java index c3abb86898e..c19a5600d2e 100644 --- a/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java @@ -1,118 +1,119 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.PhantomFluidWidget; +import gregtech.api.cover.CoverWithUI; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.sync.FixedFluidSlotSH; +import gregtech.common.covers.filter.readers.SimpleFluidFilterReader; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; +import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import org.jetbrains.annotations.Nullable; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.FluidSlot; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Row; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class SimpleFluidFilter extends FluidFilter { +public class SimpleFluidFilter extends BaseFilter { private static final int MAX_FLUID_SLOTS = 9; - protected final FluidTank[] fluidFilterTanks = new FluidTank[MAX_FLUID_SLOTS]; + private final SimpleFluidFilterReader filterReader; - public SimpleFluidFilter() { - for (int i = 0; i < MAX_FLUID_SLOTS; ++i) { - fluidFilterTanks[i] = new FluidTank(1000) { - - @Override - public void setFluid(@Nullable FluidStack fluid) { - super.setFluid(fluid); - SimpleFluidFilter.this.markDirty(); - } - }; - } + public SimpleFluidFilter(ItemStack stack) { + filterReader = new SimpleFluidFilterReader(stack, MAX_FLUID_SLOTS); } @Override + public SimpleFluidFilterReader getFilterReader() { + return filterReader; + } + public void configureFilterTanks(int amount) { - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null) - fluidTank.getFluid().amount = amount; - } + this.filterReader.setFluidAmounts(amount); this.markDirty(); } @Override - public void setMaxConfigurableFluidSize(int maxSize) { - for (FluidTank fluidTank : fluidFilterTanks) { - fluidTank.setCapacity(maxSize); - } + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("simple_fluid_filter", 98, 81) + .padding(4) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22)); } @Override - public boolean testFluid(FluidStack fluidStack) { - return checkInputFluid(fluidFilterTanks, fluidStack); + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel(getContainerStack(), 176, 168); } @Override - public int getMaxOccupiedHeight() { - return 36; + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + return new Row().coverChildrenHeight().widthRel(1f) + .child(SlotGroupWidget.builder() + .matrix("FFF", + "FFF", + "FFF") + .key('F', i -> new FluidSlot() + .syncHandler(new FixedFluidSlotSH(filterReader.getFluidTank(i)).phantom(true))) + .build().marginRight(4)) + .child(createBlacklistUI()); } @Override - public void initUI(Consumer widgetGroup) { - for (int i = 0; i < 9; ++i) { - widgetGroup.accept((new PhantomFluidWidget(10 + 18 * (i % 3), 18 * (i / 3), 18, 18, - this.fluidFilterTanks[i])) - .setBackgroundTexture(GuiTextures.SLOT).showTipSupplier(this::shouldShowTip)); + public MatchResult matchFluid(FluidStack fluidStack) { + int index = -1; + FluidStack returnable = null; + for (int i = 0; i < filterReader.getSize(); i++) { + var fluid = filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(fluidStack)) { + index = i; + returnable = fluid.copy(); + break; + } } + return MatchResult.create(index != -1, returnable, index); } - private boolean shouldShowTip() { - return showTip; - } - - public void writeToNBT(NBTTagCompound tagCompound) { - NBTTagList filterSlots = new NBTTagList(); - for (int i = 0; i < this.fluidFilterTanks.length; ++i) { - FluidTank fluidTank = this.fluidFilterTanks[i]; - if (fluidTank.getFluid() != null) { - NBTTagCompound stackTag = new NBTTagCompound(); - fluidTank.getFluid().writeToNBT(stackTag); - stackTag.setInteger("Slot", i); - filterSlots.appendTag(stackTag); + @Override + public boolean testFluid(FluidStack toTest) { + for (int i = 0; i < filterReader.getSize(); i++) { + var fluid = filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(toTest)) { + return true; } } - tagCompound.setTag("FluidFilter", filterSlots); + return false; } - public void readFromNBT(NBTTagCompound tagCompound) { - NBTTagList filterSlots = tagCompound.getTagList("FluidFilter", 10); - for (NBTBase nbtBase : filterSlots) { - NBTTagCompound stackTag = (NBTTagCompound) nbtBase; - FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(stackTag); - this.fluidFilterTanks[stackTag.getInteger("Slot")].setFluid(fluidStack); + @Override + public void initUI(Consumer widgetGroup) { + for (int i = 0; i < 9; ++i) { + widgetGroup.accept((new gregtech.api.gui.widgets.PhantomFluidWidget(10 + 18 * (i % 3), 18 * (i / 3), 18, 18, + filterReader.getFluidTank(i))) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT)); } } - public static boolean checkInputFluid(FluidTank[] fluidFilterTanks, FluidStack fluidStack) { - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null && fluidTank.getFluid().isFluidEqual(fluidStack)) { - return true; + @Override + public int getTransferLimit(FluidStack fluidStack, int transferSize) { + int limit = 0; + + for (int i = 0; i < this.filterReader.getSize(); i++) { + var fluid = this.filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(fluidStack)) { + limit = fluid.amount; } } - return false; + return isBlacklistFilter() ? transferSize : limit; } @Override - public int getFluidTransferLimit(FluidStack fluidStack) { - int limit = 0; - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null && fluidTank.getFluid().isFluidEqual(fluidStack)) { - limit = fluidTank.getFluid().amount; - break; - } - } - return limit; + public FilterType getType() { + return FilterType.FLUID; } } diff --git a/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java b/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java index 864986ca805..8bb4c556753 100644 --- a/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java @@ -1,119 +1,167 @@ package gregtech.common.covers.filter; +import gregtech.api.cover.CoverWithUI; import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.PhantomSlotWidget; import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.LargeStackSizeItemStackHandler; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.util.TextFormattingUtil; +import gregtech.common.covers.CoverItemVoidingAdvanced; +import gregtech.common.covers.CoverRoboticArm; +import gregtech.common.covers.TransferMode; +import gregtech.common.covers.VoidingMode; +import gregtech.common.covers.filter.readers.SimpleItemFilterReader; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.SyncHandlers; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import com.cleanroommc.modularui.widgets.ItemSlot; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.slot.SlotGroup; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class SimpleItemFilter extends ItemFilter { +public class SimpleItemFilter extends BaseFilter { private static final int MAX_MATCH_SLOTS = 9; + private final SimpleItemFilterReader filterReader; - protected final ItemStackHandler itemFilterSlots; - protected boolean ignoreDamage = true; - protected boolean ignoreNBT = true; - - public SimpleItemFilter() { - this.itemFilterSlots = new LargeStackSizeItemStackHandler(MAX_MATCH_SLOTS) { - - @Override - public int getSlotLimit(int slot) { - return getMaxStackSize(); - } - }; + public SimpleItemFilter(ItemStack stack) { + filterReader = new SimpleItemFilterReader(stack, MAX_MATCH_SLOTS); } @Override - protected void onMaxStackSizeChange() { - for (int i = 0; i < itemFilterSlots.getSlots(); i++) { - ItemStack itemStack = itemFilterSlots.getStackInSlot(i); - if (!itemStack.isEmpty()) { - itemStack.setCount(Math.min(itemStack.getCount(), getMaxStackSize())); - } - } - } - - public ItemStackHandler getItemFilterSlots() { - return itemFilterSlots; + public SimpleItemFilterReader getFilterReader() { + return filterReader; } - public boolean isIgnoreDamage() { - return ignoreDamage; - } - - public boolean isIgnoreNBT() { - return ignoreNBT; - } - - protected void setIgnoreDamage(boolean ignoreDamage) { - this.ignoreDamage = ignoreDamage; - markDirty(); - } - - protected void setIgnoreNBT(boolean ignoreNBT) { - this.ignoreNBT = ignoreNBT; - markDirty(); + @Override + public MatchResult matchItem(ItemStack itemStack) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + itemStack); + return MatchResult.create(matchedSlot != -1 == !isBlacklistFilter(), + filterReader.getStackInSlot(matchedSlot), matchedSlot); } @Override - public Integer matchItemStack(ItemStack itemStack) { - int itemFilterMatchIndex = itemFilterMatch(getItemFilterSlots(), isIgnoreDamage(), isIgnoreNBT(), itemStack); - return itemFilterMatchIndex == -1 ? null : itemFilterMatchIndex; + public boolean testItem(ItemStack toTest) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + toTest); + return matchedSlot != -1; } @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - Integer matchSlotIndex = (Integer) matchSlot; - ItemStack stackInFilterSlot = itemFilterSlots.getStackInSlot(matchSlotIndex); - return Math.min(stackInFilterSlot.getCount(), globalTransferLimit); + public int getTransferLimit(int matchSlot, int transferSize) { + ItemStack stackInFilterSlot = filterReader.getStackInSlot(matchSlot); + return Math.min(stackInFilterSlot.getCount(), transferSize); } @Override - public boolean showGlobalTransferLimitSlider() { - return false; + public FilterType getType() { + return FilterType.ITEM; } @Override - public int getTotalOccupiedHeight() { - return 36; + public int getTransferLimit(ItemStack stack, int transferSize) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + stack); + return getTransferLimit(matchedSlot, transferSize); } @Override - public void initUI(Consumer widgetGroup) { + public void initUI(Consumer widgetGroup) { for (int i = 0; i < 9; i++) { - widgetGroup.accept(new PhantomSlotWidget(itemFilterSlots, i, 10 + 18 * (i % 3), 18 * (i / 3)) + widgetGroup.accept(new PhantomSlotWidget(filterReader, i, 10 + 18 * (i % 3), 18 * (i / 3)) .setBackgroundTexture(GuiTextures.SLOT)); } widgetGroup.accept(new ToggleButtonWidget(74, 0, 20, 20, GuiTextures.BUTTON_FILTER_DAMAGE, - () -> ignoreDamage, this::setIgnoreDamage).setTooltipText("cover.item_filter.ignore_damage")); + filterReader::isIgnoreDamage, filterReader::setIgnoreDamage) + .setTooltipText("cover.item_filter.ignore_damage")); widgetGroup.accept(new ToggleButtonWidget(99, 0, 20, 20, GuiTextures.BUTTON_FILTER_NBT, - () -> ignoreNBT, this::setIgnoreNBT).setTooltipText("cover.item_filter.ignore_nbt")); + filterReader::isIgnoreNBT, filterReader::setIgnoreNBT).setTooltipText("cover.item_filter.ignore_nbt")); } @Override - public void writeToNBT(NBTTagCompound tagCompound) { - tagCompound.setTag("ItemFilter", itemFilterSlots.serializeNBT()); - tagCompound.setBoolean("IgnoreDamage", ignoreDamage); - tagCompound.setBoolean("IgnoreNBT", ignoreNBT); + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("simple_item_filter", 98, 81) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22).left(4)); } @Override - public void readFromNBT(NBTTagCompound tagCompound) { - this.itemFilterSlots.deserializeNBT(tagCompound.getCompoundTag("ItemFilter")); - this.ignoreDamage = tagCompound.getBoolean("IgnoreDamage"); - this.ignoreNBT = tagCompound.getBoolean("IgnoreNBT"); + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("simple_item_filter", 176, 166); } - public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage, boolean ignoreNBTData, - ItemStack itemStack) { + @SuppressWarnings("UnstableApiUsage") + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + SlotGroup filterInventory = new SlotGroup("filter_inv", 3, 1000, true); + var ignoreDamage = new BooleanSyncValue(this.filterReader::isIgnoreDamage, this.filterReader::setIgnoreDamage); + var ignoreNBT = new BooleanSyncValue(this.filterReader::isIgnoreNBT, this.filterReader::setIgnoreNBT); + + syncManager.registerSlotGroup(filterInventory); + + return new Row().coverChildren() + .child(SlotGroupWidget.builder() + .matrix("XXX", + "XXX", + "XXX") + .key('X', index -> new ItemSlot() + .tooltip(tooltip -> { + tooltip.setAutoUpdate(true); + tooltip.textColor(Color.GREY.main); + }) + .tooltipBuilder(tooltip -> { + if (dirtyNotifiable instanceof CoverRoboticArm coverArm && + coverArm.getTransferMode() != TransferMode.TRANSFER_ANY || + dirtyNotifiable instanceof CoverItemVoidingAdvanced coverItem && + coverItem.getVoidingMode() != VoidingMode.VOID_ANY) { + tooltip.addLine(IKey.lang("cover.item_filter.config_amount")); + int count = this.filterReader.getTagAt(index) + .getInteger(SimpleItemFilterReader.COUNT); + if (count > 0) + tooltip.addLine( + IKey.format("Count: %s", TextFormattingUtil.formatNumbers(count))); + } + }) + .slot(SyncHandlers.phantomItemSlot(this.filterReader, index) + .ignoreMaxStackSize(true) + .slotGroup(filterInventory) + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (onlyAmountChanged && !init) { + markDirty(); + } + }))) + .build().marginRight(4)) + .child(new Column().width(18).coverChildren() + .child(createBlacklistUI()) + .child(new CycleButtonWidget() + .value(ignoreDamage) + .textureGetter(state -> GTGuiTextures.BUTTON_IGNORE_DAMAGE[state]) + .addTooltip(0, IKey.lang("cover.item_filter.ignore_damage.disabled")) + .addTooltip(1, IKey.lang("cover.item_filter.ignore_damage.enabled"))) + .child(new CycleButtonWidget() + .value(ignoreNBT) + .textureGetter(state -> GTGuiTextures.BUTTON_IGNORE_NBT[state]) + .addTooltip(0, IKey.lang("cover.item_filter.ignore_nbt.disabled")) + .addTooltip(1, IKey.lang("cover.item_filter.ignore_nbt.enabled")))); + } + + public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage, + boolean ignoreNBTData, ItemStack itemStack) { for (int i = 0; i < filterSlots.getSlots(); i++) { ItemStack filterStack = filterSlots.getStackInSlot(i); if (!filterStack.isEmpty() && areItemsEqual(ignoreDamage, ignoreNBTData, filterStack, itemStack)) { @@ -123,8 +171,8 @@ public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage return -1; } - private static boolean areItemsEqual(boolean ignoreDamage, boolean ignoreNBTData, ItemStack filterStack, - ItemStack itemStack) { + private static boolean areItemsEqual(boolean ignoreDamage, boolean ignoreNBTData, + ItemStack filterStack, ItemStack itemStack) { if (ignoreDamage) { if (!filterStack.isItemEqualIgnoreDurability(itemStack)) { return false; diff --git a/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java b/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java index a655d22f732..651c768e4dd 100644 --- a/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java @@ -1,95 +1,144 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.Widget; +import gregtech.api.cover.CoverWithUI; import gregtech.api.gui.widgets.CycleButtonWidget; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.RecipeMaps; import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.api.unification.stack.ItemAndMetadata; +import gregtech.common.covers.filter.readers.SmartItemFilterReader; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.IStringSerializable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.BoolValue; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.Collections; -import java.util.Map; import java.util.function.Consumer; -public class SmartItemFilter extends ItemFilter { +public class SmartItemFilter extends BaseFilter { - private SmartFilteringMode filteringMode = SmartFilteringMode.ELECTROLYZER; + private final SmartItemFilterReader filterReader; - public SmartFilteringMode getFilteringMode() { - return filteringMode; + public SmartItemFilter(ItemStack stack) { + filterReader = new SmartItemFilterReader(stack); } - public void setFilteringMode(SmartFilteringMode filteringMode) { - this.filteringMode = filteringMode; - markDirty(); + @Override + public SmartItemFilterReader getFilterReader() { + return filterReader; } - @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - ItemAndMetadataAndStackSize itemAndMetadata = (ItemAndMetadataAndStackSize) matchSlot; - return itemAndMetadata.transferStackSize; + public SmartFilteringMode getFilteringMode() { + return this.filterReader.getFilteringMode(); } @Override - public Object matchItemStack(ItemStack itemStack) { - ItemAndMetadata itemAndMetadata = new ItemAndMetadata(itemStack); - Integer cachedTransferRateValue = filteringMode.transferStackSizesCache.get(itemAndMetadata); + public int getTransferLimit(ItemStack stack, int globalTransferLimit) { + ItemAndMetadata itemAndMetadata = new ItemAndMetadata(stack); + var filterMode = this.filterReader.getFilteringMode(); + int cachedTransferRateValue = filterMode.transferStackSizesCache.getOrDefault(itemAndMetadata, -1); - if (cachedTransferRateValue == null) { - ItemStack infinitelyBigStack = itemStack.copy(); + if (cachedTransferRateValue == -1) { + ItemStack infinitelyBigStack = stack.copy(); infinitelyBigStack.setCount(Integer.MAX_VALUE); - Recipe recipe = filteringMode.recipeMap.findRecipe(Long.MAX_VALUE, + Recipe recipe = filterMode.recipeMap.findRecipe(Long.MAX_VALUE, Collections.singletonList(infinitelyBigStack), Collections.emptyList()); if (recipe == null) { - filteringMode.transferStackSizesCache.put(itemAndMetadata, 0); + filterMode.transferStackSizesCache.put(itemAndMetadata, 0); cachedTransferRateValue = 0; } else { GTRecipeInput inputIngredient = recipe.getInputs().iterator().next(); - filteringMode.transferStackSizesCache.put(itemAndMetadata, inputIngredient.getAmount()); + filterMode.transferStackSizesCache.put(itemAndMetadata, inputIngredient.getAmount()); cachedTransferRateValue = inputIngredient.getAmount(); } } - if (cachedTransferRateValue == 0) { - return null; - } - return new ItemAndMetadataAndStackSize(itemAndMetadata, cachedTransferRateValue); + return cachedTransferRateValue; + } + + @Override + public MatchResult matchItem(ItemStack itemStack) { + var stack = itemStack.copy(); + stack.setCount(getTransferLimit(itemStack, Integer.MAX_VALUE)); + return MatchResult.create(stack.getCount() > 0 != isBlacklistFilter(), stack, + this.getFilteringMode().ordinal()); + } + + @Override + public boolean testItem(ItemStack toTest) { + return getTransferLimit(toTest, Integer.MAX_VALUE) > 0; } @Override - public void initUI(Consumer widgetGroup) { + public FilterType getType() { + return FilterType.ITEM; + } + + @Override + public void initUI(Consumer widgetGroup) { widgetGroup.accept(new CycleButtonWidget(10, 0, 75, 20, - SmartFilteringMode.class, this::getFilteringMode, this::setFilteringMode) + SmartFilteringMode.class, filterReader::getFilteringMode, filterReader::setFilteringMode) .setTooltipHoverString("cover.smart_item_filter.filtering_mode.description")); } @Override - public int getTotalOccupiedHeight() { - return 20; + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("smart_item_filter", 98 + 27, 81) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22).left(4)); } @Override - public boolean showGlobalTransferLimitSlider() { - return true; + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("smart_item_filter", 100, 100).padding(7); } @Override - public void writeToNBT(NBTTagCompound tagCompound) { - tagCompound.setInteger("FilterMode", filteringMode.ordinal()); + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + var filterMode = new EnumSyncValue<>(SmartFilteringMode.class, filterReader::getFilteringMode, + filterReader::setFilteringMode); + syncManager.syncValue("filter_mode", filterMode); + + return new Row().coverChildren() + .child(new Column().coverChildren().marginRight(4) + .child(createFilterModeButton(filterMode, SmartFilteringMode.ELECTROLYZER)) + .child(createFilterModeButton(filterMode, SmartFilteringMode.CENTRIFUGE)) + .child(createFilterModeButton(filterMode, SmartFilteringMode.SIFTER))) + .child(createBlacklistUI()); + } + + private Widget createFilterModeButton(EnumSyncValue value, + SmartFilteringMode mode) { + return new ToggleButton().height(18).width(18 * 5) + .value(boolValueOf(value, mode)) + .background(GTGuiTextures.MC_BUTTON) + .selectedBackground(GTGuiTextures.MC_BUTTON_DISABLED) + .overlay(IKey.lang(mode.getName()).color(Color.WHITE.darker(1))); + } + + protected > BoolValue.Dynamic boolValueOf(EnumSyncValue syncValue, T value) { + return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); } @Override - public void readFromNBT(NBTTagCompound tagCompound) { - this.filteringMode = SmartFilteringMode.values()[tagCompound.getInteger("FilterMode")]; + public boolean showGlobalTransferLimitSlider() { + return true; } private static class ItemAndMetadataAndStackSize { @@ -122,7 +171,8 @@ public enum SmartFilteringMode implements IStringSerializable { CENTRIFUGE("cover.smart_item_filter.filtering_mode.centrifuge", RecipeMaps.CENTRIFUGE_RECIPES), SIFTER("cover.smart_item_filter.filtering_mode.sifter", RecipeMaps.SIFTER_RECIPES); - private final Map transferStackSizesCache = new Object2IntOpenHashMap<>(); + public static final SmartFilteringMode[] VALUES = values(); + private final Object2IntOpenHashMap transferStackSizesCache = new Object2IntOpenHashMap<>(); public final String localeName; public final RecipeMap recipeMap; diff --git a/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java b/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java index f2c08f856b3..c43d7487467 100644 --- a/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java +++ b/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java @@ -1,19 +1,29 @@ package gregtech.common.covers.filter; import gregtech.api.gui.widgets.AbstractWidgetGroup; +import gregtech.api.util.GTLog; import gregtech.api.util.Position; +import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; +import org.jetbrains.annotations.ApiStatus; + +import java.io.IOException; import java.util.function.Supplier; +/** + * @deprecated in favor of new MUI + */ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.10") public class WidgetGroupFluidFilter extends AbstractWidgetGroup { - private final Supplier fluidFilterSupplier; + private final Supplier fluidFilterSupplier; private final Supplier showTipSupplier; - private FluidFilter fluidFilter; + private BaseFilter fluidFilter; - public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSupplier, + public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSupplier, Supplier showTipSupplier) { super(new Position(18 + 5, yPosition)); this.fluidFilterSupplier = fluidFilterSupplier; @@ -23,7 +33,7 @@ public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSu @Override public void detectAndSendChanges() { super.detectAndSendChanges(); - FluidFilter newFluidFilter = fluidFilterSupplier.get(); + BaseFilter newFluidFilter = fluidFilterSupplier.get(); if (fluidFilter != newFluidFilter) { clearAllWidgets(); this.fluidFilter = newFluidFilter; @@ -33,17 +43,16 @@ public void detectAndSendChanges() { writeUpdateInfo(2, buffer -> { if (fluidFilter != null) { buffer.writeBoolean(true); - int filterId = FilterTypeRegistry.getIdForFluidFilter(fluidFilter); - buffer.writeVarInt(filterId); + buffer.writeItemStack(fluidFilter.getContainerStack()); } else { buffer.writeBoolean(false); } }); } - if (fluidFilter != null && showTipSupplier != null && fluidFilter.showTip != showTipSupplier.get()) { - fluidFilter.showTip = showTipSupplier.get(); - writeUpdateInfo(3, buffer -> buffer.writeBoolean(fluidFilter.showTip)); - } + // if (fluidFilter != null && showTipSupplier != null && fluidFilter.showTip != showTipSupplier.get()) { + // fluidFilter.showTip = showTipSupplier.get(); + // writeUpdateInfo(3, buffer -> buffer.writeBoolean(fluidFilter.showTip)); + // } } @Override @@ -52,12 +61,18 @@ public void readUpdateInfo(int id, PacketBuffer buffer) { if (id == 2) { clearAllWidgets(); if (buffer.readBoolean()) { - int filterId = buffer.readVarInt(); - this.fluidFilter = FilterTypeRegistry.createFluidFilterById(filterId); + ItemStack stack; + try { + stack = buffer.readItemStack(); + } catch (IOException e) { + GTLog.logger.warn(e); + return; + } + this.fluidFilter = BaseFilter.getFilterFromStack(stack); this.fluidFilter.initUI(this::addWidget); } } else if (id == 3) { - fluidFilter.showTip = buffer.readBoolean(); + // fluidFilter.showTip = buffer.readBoolean(); } } } diff --git a/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java b/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java index d5601f2b2ab..9f26302fb2f 100644 --- a/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java @@ -5,15 +5,23 @@ import net.minecraft.network.PacketBuffer; +import org.jetbrains.annotations.ApiStatus; + +import java.io.IOException; import java.util.function.Supplier; +/** + * @deprecated in favor of new MUI + */ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.10") public class WidgetGroupItemFilter extends AbstractWidgetGroup { - private final Supplier itemFilterSupplier; - private ItemFilter itemFilter; + private final Supplier itemFilterSupplier; + private BaseFilter itemFilter; private int maxStackSize = 1; - public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSupplier) { + public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSupplier) { super(new Position(0, yPosition)); this.itemFilterSupplier = itemFilterSupplier; } @@ -21,7 +29,7 @@ public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSuppl @Override public void detectAndSendChanges() { super.detectAndSendChanges(); - ItemFilter newItemFilter = itemFilterSupplier.get(); + BaseFilter newItemFilter = itemFilterSupplier.get(); if (itemFilter != newItemFilter) { clearAllWidgets(); this.itemFilter = newItemFilter; @@ -31,14 +39,13 @@ public void detectAndSendChanges() { writeUpdateInfo(2, buffer -> { if (itemFilter != null) { buffer.writeBoolean(true); - int filterId = FilterTypeRegistry.getIdForItemFilter(itemFilter); - buffer.writeVarInt(filterId); + buffer.writeItemStack(itemFilter.getContainerStack()); } else { buffer.writeBoolean(false); } }); } - int newMaxStackSize = itemFilter == null ? 1 : itemFilter.getMaxStackSize(); + int newMaxStackSize = itemFilter == null ? 1 : itemFilter.getMaxTransferSize(); if (maxStackSize != newMaxStackSize) { this.maxStackSize = newMaxStackSize; writeUpdateInfo(3, buffer -> buffer.writeVarInt(maxStackSize)); @@ -51,15 +58,19 @@ public void readUpdateInfo(int id, PacketBuffer buffer) { if (id == 2) { clearAllWidgets(); if (buffer.readBoolean()) { - int filterId = buffer.readVarInt(); - this.itemFilter = FilterTypeRegistry.createItemFilterById(filterId); - this.itemFilter.initUI(this::addWidget); - this.itemFilter.setMaxStackSize(maxStackSize); + // int filterId = buffer.readVarInt(); + try { + this.itemFilter = BaseFilter.getFilterFromStack(buffer.readItemStack()); + this.itemFilter.initUI(this::addWidget); + this.itemFilter.setMaxTransferSize(maxStackSize); + } catch (IOException e) { + throw new RuntimeException(e); + } } } else if (id == 3) { this.maxStackSize = buffer.readVarInt(); if (itemFilter != null) { - itemFilter.setMaxStackSize(maxStackSize); + itemFilter.setMaxTransferSize(maxStackSize); } } } diff --git a/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java new file mode 100644 index 00000000000..eee6a16a52a --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java @@ -0,0 +1,124 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.NotNull; + +public class BaseFilterReader implements FilterReader, INBTSerializable { + + protected ItemStack container; + private IDirtyNotifiable dirtyNotifiable; + private final int size; + private int maxTransferRate = 1; + protected static final String BLACKLIST = "IsBlacklist"; + protected static final String FILTER_CONTENTS = "FilterSlots"; + protected static final String KEY_LEGACY_FILTER = "Filter"; + + public BaseFilterReader(ItemStack container, int slots) { + this.container = container; + this.size = slots; + } + + @Override + public ItemStack getContainer() { + return this.container; + } + + @Override + public void readStack(@NotNull ItemStack stack) { + this.container = stack; + } + + public @NotNull NBTTagList getInventoryNbt() { + var nbt = getStackTag(); + if (!nbt.hasKey(FILTER_CONTENTS)) { + NBTTagList list = new NBTTagList(); + for (int i = 0; i < getSize(); i++) { + list.appendTag(new NBTTagCompound()); + } + nbt.setTag(FILTER_CONTENTS, list); + } + return nbt.getTagList(FILTER_CONTENTS, Constants.NBT.TAG_COMPOUND); + } + + public @NotNull NBTTagCompound getStackTag() { + NBTTagCompound nbt = this.container.getTagCompound(); + if (nbt == null) { + nbt = new NBTTagCompound(); + this.container.setTagCompound(nbt); + } + return nbt; + } + + @Override + public int getSize() { + return this.size; + } + + public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { + this.dirtyNotifiable = dirtyNotifiable; + } + + public final void markDirty() { + if (dirtyNotifiable != null) { + dirtyNotifiable.markAsDirty(); + } + } + + public void onTransferRateChange() {} + + public final void setBlacklistFilter(boolean blacklistFilter) { + if (getStackTag().getBoolean(BLACKLIST) != blacklistFilter) { + if (blacklistFilter) + getStackTag().setBoolean(BLACKLIST, true); + else + getStackTag().removeTag(BLACKLIST); + onTransferRateChange(); + markDirty(); + } + } + + public final boolean isBlacklistFilter() { + return getStackTag().getBoolean(BLACKLIST); + } + + public void setMaxTransferRate(int transferRate) { + transferRate = MathHelper.clamp(transferRate, 1, Integer.MAX_VALUE); + if (this.maxTransferRate != transferRate) { + this.maxTransferRate = transferRate; + onTransferRateChange(); + } + } + + public int getMaxTransferRate() { + return isBlacklistFilter() ? 1 : this.maxTransferRate; + } + + @Override + public boolean validateSlotIndex(int slot) { + return slot >= 0 && slot < getSize(); + } + + @Override + public NBTTagCompound serializeNBT() { + return getStackTag(); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + if (nbt.hasKey(BLACKLIST)) + setBlacklistFilter(nbt.getBoolean(BLACKLIST)); + } + + public void handleLegacyNBT(NBTTagCompound tag) { + if (tag.hasKey(BLACKLIST)) + setBlacklistFilter(tag.getBoolean(BLACKLIST)); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java new file mode 100644 index 00000000000..34efe945268 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java @@ -0,0 +1,32 @@ +package gregtech.common.covers.filter.readers; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import org.jetbrains.annotations.NotNull; + +public interface FilterReader { + + ItemStack getContainer(); + + void readStack(ItemStack stack); + + @NotNull + NBTTagList getInventoryNbt(); + + @NotNull + NBTTagCompound getStackTag(); + + int getSize(); + + boolean validateSlotIndex(int slot); + + @NotNull + default NBTTagCompound getTagAt(int i) { + if (validateSlotIndex(i)) { + return getInventoryNbt().getCompoundTagAt(i); + } + return new NBTTagCompound(); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java new file mode 100644 index 00000000000..070ec7fe764 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java @@ -0,0 +1,123 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.oreglob.OreGlob; +import gregtech.api.util.oreglob.OreGlobCompileResult; +import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; + +public class OreDictFilterReader extends SimpleItemFilterReader { + + private static final String EXPRESSION = "OreDictionaryFilter"; + private static final String CASE_SENSITIVE = "caseSensitive"; + private static final String MATCH_ALL = "matchAll"; + + private OreGlob glob = ImpossibleOreGlob.getInstance(); + private OreGlobCompileResult result; + + public OreDictFilterReader(ItemStack container) { + super(container, 0); + } + + public void setExpression(String expression) { + if (getStackTag().getString(EXPRESSION).equals(expression)) + return; + + getStackTag().setString(EXPRESSION, expression); + recompile(); + markDirty(); + } + + public String getExpression() { + return getStackTag().getString(EXPRESSION); + } + + public void setCaseSensitive(boolean caseSensitive) { + if (isCaseSensitive() == caseSensitive) + return; + + if (!caseSensitive) + getStackTag().setBoolean(CASE_SENSITIVE, false); + else + getStackTag().removeTag(CASE_SENSITIVE); + recompile(); + markDirty(); + } + + public boolean isCaseSensitive() { + return !getStackTag().hasKey(CASE_SENSITIVE); + } + + public void setMatchAll(boolean matchAll) { + if (shouldMatchAll() == matchAll) + return; + + if (!matchAll) + getStackTag().setBoolean(MATCH_ALL, false); + else + getStackTag().removeTag(MATCH_ALL); + + markDirty(); + } + + /** + * {@code false} requires any of the entry to be match in order for the match to be success, {@code true} + * requires + * all entries to match + */ + public boolean shouldMatchAll() { + return !getStackTag().hasKey(MATCH_ALL); + } + + @NotNull + public OreGlob getGlob() { + return this.glob; + } + + public OreGlobCompileResult getResult() { + return this.result; + } + + public void recompile() { + String expr = getExpression(); + if (!expr.isEmpty()) { + result = OreGlob.compile(expr, !isCaseSensitive()); + this.glob = result.getInstance(); + } else { + this.glob = ImpossibleOreGlob.getInstance(); + result = null; + } + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + + if (nbt.hasKey(EXPRESSION)) + this.setExpression(nbt.getString(EXPRESSION)); + + if (nbt.hasKey(CASE_SENSITIVE)) + this.setCaseSensitive(nbt.getBoolean(CASE_SENSITIVE)); + + if (nbt.hasKey(MATCH_ALL)) + this.setMatchAll(nbt.getBoolean(MATCH_ALL)); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + + var legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + if (legacyFilter.hasKey(EXPRESSION)) + this.setExpression(legacyFilter.getString(EXPRESSION)); + + if (legacyFilter.hasKey(CASE_SENSITIVE)) + this.setCaseSensitive(legacyFilter.getBoolean(CASE_SENSITIVE)); + + if (legacyFilter.hasKey(MATCH_ALL)) + this.setMatchAll(legacyFilter.getBoolean(MATCH_ALL)); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java new file mode 100644 index 00000000000..ea38dafd569 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java @@ -0,0 +1,181 @@ +package gregtech.common.covers.filter.readers; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; + +import org.jetbrains.annotations.Nullable; + +public class SimpleFluidFilterReader extends BaseFilterReader { + + protected WritableFluidTank[] fluidTanks; + protected static final String CAPACITY = "Capacity"; + + protected static final String LEGACY_FLUIDFILTER_KEY = "FluidFilter"; + + public SimpleFluidFilterReader(ItemStack container, int slots) { + super(container, slots); + fluidTanks = new WritableFluidTank[slots]; + for (int i = 0; i < fluidTanks.length; i++) { + fluidTanks[i] = new WritableFluidTank(this, getInventoryNbt().getCompoundTagAt(i)); + } + setCapacity(getStackTag().hasKey(CAPACITY) ? getCapacity() : 1000); + } + + public final boolean shouldShowAmount() { + return getMaxTransferRate() > 1; + } + + @Nullable + public FluidStack getFluidStack(int i) { + return getFluidTank(i).getFluid(); + } + + public void setCapacity(int capacity) { + getStackTag().setInteger(CAPACITY, capacity); + markDirty(); + } + + public int getCapacity() { + return getStackTag().getInteger(CAPACITY); + } + + public WritableFluidTank getFluidTank(int i) { + return fluidTanks[i]; + } + + public void setFluidAmounts(int amount) { + for (int i = 0; i < getSize(); i++) { + getFluidTank(i).setFluidAmount(amount); + } + } + + @Override + public void onTransferRateChange() { + for (int i = 0; i < getSize(); i++) { + var stack = getFluidStack(i); + if (stack == null) continue; + getFluidTank(i).setFluidAmount(Math.min(stack.amount, getMaxTransferRate())); + } + setCapacity(getMaxTransferRate()); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + NBTTagCompound legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + + NBTTagList filterSlots = legacyFilter.getTagList(LEGACY_FLUIDFILTER_KEY, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < filterSlots.tagCount(); i++) { + NBTTagCompound stackTag = filterSlots.getCompoundTagAt(i); + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(stackTag); + if (fluidStack == null) continue; + int slot = stackTag.getInteger("Slot"); + getFluidTank(slot).setFluid(fluidStack); + } + } + + public class WritableFluidTank extends FluidTank { + + private final NBTTagCompound fluidTank; + private final SimpleFluidFilterReader filterReader; + protected static final String FLUID_AMOUNT = "Amount"; + protected static final String FLUID = "Fluid"; + protected static final String EMPTY = "Empty"; + + protected WritableFluidTank(SimpleFluidFilterReader filterReader, NBTTagCompound fluidTank) { + super(0); + this.filterReader = filterReader; + this.fluidTank = fluidTank; + } + + public void setFluidAmount(int amount) { + if (amount <= 0) { + setFluid(null); + } else if (this.fluidTank.hasKey(FLUID)) { + this.fluidTank + .getCompoundTag(FLUID) + .setInteger(FLUID_AMOUNT, amount); + markDirty(); + } + } + + public boolean isEmpty() { + return !this.fluidTank.hasKey(FLUID); + } + + protected @Nullable NBTTagCompound getFluidTag() { + if (isEmpty()) { + return null; + } + + return this.fluidTank.getCompoundTag(FLUID); + } + + @Override + public @Nullable FluidStack getFluid() { + return FluidStack.loadFluidStackFromNBT(getFluidTag()); + } + + @Override + public void setFluid(@Nullable FluidStack stack) { + if (stack == null) { + this.fluidTank.removeTag(FLUID); + } else { + this.fluidTank.setTag(FLUID, stack.writeToNBT(new NBTTagCompound())); + } + markDirty(); + } + + public boolean showAmount() { + return this.filterReader.shouldShowAmount(); + } + + @Override + public int getFluidAmount() { + return this.fluidTank + .getCompoundTag(FLUID) + .getInteger(FLUID_AMOUNT); + } + + @Override + public int getCapacity() { + return this.filterReader.getCapacity(); + } + + // getFluid() is checked for nullability, suppress + @SuppressWarnings("DataFlowIssue") + @Override + public int fill(FluidStack resource, boolean doFill) { + if (isEmpty() || !getFluid().isFluidEqual(resource)) { + setFluid(resource); + if (!showAmount()) setFluidAmount(1); + return resource.amount; + } else if (showAmount()) { + var fluid = getFluid(); + int accepted = Math.min(resource.amount, getCapacity() - fluid.amount); + fluid.amount += accepted; + setFluid(fluid); + return accepted; + } + return 0; + } + + // getFluid() is checked for nullability, suppress + @SuppressWarnings("DataFlowIssue") + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + if (isEmpty()) return null; + FluidStack fluid = getFluid(); + + fluid.amount -= Math.min(fluid.amount, maxDrain); + + setFluidAmount(fluid.amount); + markDirty(); + return fluid; + } + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java new file mode 100644 index 00000000000..7e9ea677b3e --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java @@ -0,0 +1,193 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.GTUtility; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +import org.jetbrains.annotations.NotNull; + +public class SimpleItemFilterReader extends BaseFilterReader implements IItemHandlerModifiable { + + public static final String COUNT = "Count"; + protected static final String LEGACY_ITEM_KEY = "ItemFilter"; + protected static final String LEGACY_STACK_SIZE = "BigStackSize"; + public static final String RESPECT_NBT = "IgnoreNBT"; + public static final String RESPECT_DAMAGE = "IgnoreDamage"; + + public SimpleItemFilterReader(ItemStack container, int slots) { + super(container, slots); + } + + public void setIgnoreDamage(boolean ignoreDamage) { + if (!getStackTag().getBoolean(RESPECT_DAMAGE) == ignoreDamage) + return; + + if (ignoreDamage) + getStackTag().removeTag(RESPECT_DAMAGE); + else + getStackTag().setBoolean(RESPECT_DAMAGE, true); + markDirty(); + } + + @Override + public int getSlots() { + return getSize(); + } + + public void setIgnoreNBT(boolean ignoreNBT) { + if (!getStackTag().getBoolean(RESPECT_NBT) == ignoreNBT) + return; + + if (ignoreNBT) + getStackTag().removeTag(RESPECT_NBT); + else + getStackTag().setBoolean(RESPECT_NBT, true); + markDirty(); + } + + public boolean isIgnoreDamage() { + return !getStackTag().getBoolean(RESPECT_DAMAGE); + } + + public boolean isIgnoreNBT() { + return !getStackTag().getBoolean(RESPECT_NBT); + } + + @Override + public int getSlotLimit(int slot) { + return getMaxTransferRate(); + } + + @NotNull + @Override + public ItemStack getStackInSlot(int slot) { + if (validateSlotIndex(slot)) { + NBTTagCompound item = getTagAt(slot); + return item.isEmpty() ? ItemStack.EMPTY : new ItemStack(item); + } + return ItemStack.EMPTY; + } + + @Override + public void setStackInSlot(int slot, ItemStack stack) { + if (validateSlotIndex(slot)) { + if (!stack.isEmpty()) { + stack.setCount(Math.min(stack.getCount(), isBlacklistFilter() ? 1 : getMaxTransferRate())); + } + NBTTagList list = getInventoryNbt(); + list.set(slot, stack.isEmpty() ? new NBTTagCompound() : stack.serializeNBT()); + } + } + + @NotNull + @Override + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + if (stack.isEmpty()) return stack; + ItemStack existing = getStackInSlot(slot); + + int limit = getStackLimit(slot, stack); + + if (!existing.isEmpty()) { + if (!ItemHandlerHelper.canItemStacksStack(stack, existing)) + return stack; + + limit -= existing.getCount(); + } + + if (limit <= 0) return stack; + + boolean reachedLimit = stack.getCount() > limit; + + if (!simulate) { + if (existing.isEmpty()) { + setStackInSlot(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack); + } else { + existing.grow(reachedLimit ? limit : stack.getCount()); + setStackInSlot(slot, existing); + } + } + + return reachedLimit ? GTUtility.copy(stack.getCount() - limit, stack) : ItemStack.EMPTY; + } + + @NotNull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) return ItemStack.EMPTY; + + ItemStack existing = getStackInSlot(slot); + if (existing.isEmpty()) return ItemStack.EMPTY; + + int toExtract = Math.min(amount, existing.getMaxStackSize()); + + if (existing.getCount() <= toExtract) { + if (!simulate) { + setStackInSlot(slot, ItemStack.EMPTY); + } + return existing; + } else { + if (!simulate) { + setStackInSlot(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract)); + } + + return GTUtility.copy(toExtract, existing); + } + } + + protected int getStackLimit(int slot, @NotNull ItemStack stack) { + return Math.min(getSlotLimit(slot), stack.getMaxStackSize()); + } + + @Override + public void onTransferRateChange() { + for (int i = 0; i < getSlots(); i++) { + ItemStack itemStack = getStackInSlot(i); + if (!itemStack.isEmpty()) { + itemStack.setCount(Math.min(itemStack.getCount(), isBlacklistFilter() ? 1 : getMaxTransferRate())); + setStackInSlot(i, itemStack); + } + } + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + + if (nbt.hasKey(RESPECT_DAMAGE)) + this.setIgnoreDamage(nbt.getBoolean(RESPECT_DAMAGE)); + + if (nbt.hasKey(RESPECT_NBT)) + this.setIgnoreNBT(nbt.getBoolean(RESPECT_NBT)); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + NBTTagCompound legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + + if (legacyFilter.hasKey(LEGACY_ITEM_KEY)) { + var temp = new ItemStackHandler(); + var legacyTag = legacyFilter.getCompoundTag(LEGACY_ITEM_KEY); + var stackSizes = legacyTag.getCompoundTag(LEGACY_STACK_SIZE); + + temp.deserializeNBT(legacyTag); + for (int i = 0; i < temp.getSlots(); i++) { + var stack = temp.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + if (stackSizes.hasKey(String.valueOf(i))) + stack.setCount(stackSizes.getInteger(String.valueOf(i))); + + var stackTag = stack.serializeNBT(); + stackTag.setInteger(COUNT, stack.getCount()); + getInventoryNbt().set(i, stackTag); + } + } + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java new file mode 100644 index 00000000000..ca96ed549c2 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java @@ -0,0 +1,40 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.common.covers.filter.SmartItemFilter; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +public class SmartItemFilterReader extends SimpleItemFilterReader { + + private static final String FILTER_MODE = "FilterMode"; + + public SmartItemFilterReader(ItemStack container) { + super(container, 0); + } + + public SmartItemFilter.SmartFilteringMode getFilteringMode() { + if (!getStackTag().hasKey(FILTER_MODE)) + setFilteringMode(SmartItemFilter.SmartFilteringMode.ELECTROLYZER); + + return SmartItemFilter.SmartFilteringMode.VALUES[getStackTag().getInteger(FILTER_MODE)]; + } + + public void setFilteringMode(SmartItemFilter.SmartFilteringMode filteringMode) { + getStackTag().setInteger(FILTER_MODE, filteringMode.ordinal()); + markDirty(); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + this.setFilteringMode(SmartItemFilter.SmartFilteringMode.VALUES[nbt.getInteger(FILTER_MODE)]); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + var legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + this.setFilteringMode(SmartItemFilter.SmartFilteringMode.VALUES[legacyFilter.getInteger(FILTER_MODE)]); + } +} diff --git a/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java b/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java deleted file mode 100644 index 8acea5527f7..00000000000 --- a/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java +++ /dev/null @@ -1,127 +0,0 @@ -package gregtech.common.gui.widget; - -import gregtech.api.gui.widgets.TextFieldWidget2; - -import net.minecraft.util.text.TextFormatting; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class HighlightedTextField extends TextFieldWidget2 { - - @Nullable - private Consumer highlightRule; - @Nullable - private TextHighlighter formatResult; - - public HighlightedTextField(int x, int y, int width, int height, Supplier supplier, - Consumer setter) { - super(x, y, width, height, supplier, setter); - } - - /** - * Text highlighter applied only in rendering text. Only formatting characters can be inserted. - * - * @param highlightRule Consumer for text highlighter - * @return This - */ - public HighlightedTextField setHighlightRule(Consumer highlightRule) { - this.highlightRule = highlightRule; - return this; - } - - @Override - public void setText(String text) { - super.setText(text); - this.formatResult = null; - } - - @Override - protected String getRenderText() { - if (this.formatResult == null) { - if (this.highlightRule == null) { - return getText(); - } - TextHighlighter highlighter = new TextHighlighter(getText()); - this.highlightRule.accept(highlighter); - this.formatResult = highlighter; - return highlighter.getFormattedText(); - } - return this.formatResult.getFormattedText(); - } - - @Override - protected int toOriginalTextIndex(int renderTextIndex) { - return formatResult != null ? formatResult.toOriginalTextIndex(renderTextIndex) : renderTextIndex; - } - - @Override - protected int toRenderTextIndex(int originalTextIndex) { - return formatResult != null ? formatResult.toFormattedTextIndex(originalTextIndex) : originalTextIndex; - } - - public static final class TextHighlighter { - - private final String originalText; - private final StringBuilder formattedTextBuilder; - - private final IntList formatOriginalIndices = new IntArrayList(); - - @Nullable - private String formattedTextCache; - - public TextHighlighter(String originalText) { - this.originalText = originalText; - this.formattedTextBuilder = new StringBuilder(originalText); - } - - public String getOriginalText() { - return this.originalText; - } - - public String getFormattedText() { - if (this.formattedTextCache == null) { - return this.formattedTextCache = this.formattedTextBuilder.toString(); - } - return this.formattedTextCache; - } - - public int toFormattedTextIndex(int originalTextIndex) { - int i = 0; - for (; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) > originalTextIndex) { - break; - } - } - return originalTextIndex + i * 2; - } - - public int toOriginalTextIndex(int formattedTextIndex) { - int i = 0; - for (; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) + i * 2 >= formattedTextIndex) { - break; - } - } - return formattedTextIndex - i * 2; - } - - public void format(int index, TextFormatting format) { - if (index < 0) index = 0; - else if (index > originalText.length()) return; - formattedTextBuilder.insert(toFormattedTextIndex(index), format.toString()); - formattedTextCache = null; - for (int i = 0; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) > index) { - formatOriginalIndices.add(i, index); - return; - } - } - formatOriginalIndices.add(index); - } - } -} diff --git a/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java b/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java deleted file mode 100644 index b30a48cd25d..00000000000 --- a/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java +++ /dev/null @@ -1,111 +0,0 @@ -package gregtech.common.gui.widget.orefilter; - -import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.ingredient.IGhostIngredientTarget; -import gregtech.api.unification.OreDictUnifier; -import gregtech.api.util.Position; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import com.google.common.collect.Lists; -import mezz.jei.api.gui.IGhostIngredientHandler; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -public class ItemOreFilterTestSlot extends OreFilterTestSlot implements IGhostIngredientTarget { - - @NotNull - private ItemStack testStack = ItemStack.EMPTY; - - public ItemOreFilterTestSlot(int xPosition, int yPosition) { - super(xPosition, yPosition); - } - - @NotNull - public ItemStack getTestStack() { - return testStack; - } - - public void setTestStack(@NotNull ItemStack testStack) { - this.testStack = testStack; - updatePreview(); - } - - @Nullable - @Override - protected Set getTestCandidates() { - return this.testStack.isEmpty() ? null : OreDictUnifier.getOreDictionaryNames(this.testStack); - } - - @Override - protected void renderSlotContents(float partialTicks, IRenderContext context) { - Position pos = getPosition(); - if (!testStack.isEmpty()) { - GlStateManager.enableDepth(); - RenderHelper.enableGUIStandardItemLighting(); - GlStateManager.pushMatrix(); - RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); - itemRender.renderItemAndEffectIntoGUI(testStack, pos.x + 1, pos.y + 1); - itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRenderer, testStack, pos.x + 1, pos.y + 1, - null); - GlStateManager.popMatrix(); - RenderHelper.disableStandardItemLighting(); - } - } - - @Override - @SideOnly(Side.CLIENT) - public boolean mouseClicked(int mouseX, int mouseY, int button) { - if (isMouseOverElement(mouseX, mouseY)) { - EntityPlayer player = Minecraft.getMinecraft().player; - putItem(player.inventory.getItemStack()); - return true; - } - return false; - } - - private void putItem(ItemStack stack) { - ItemStack testStack = getTestStack(); - if ((stack.isEmpty() ^ testStack.isEmpty()) || !testStack.isItemEqual(stack) || - !ItemStack.areItemStackTagsEqual(testStack, stack)) { - ItemStack copy = stack.copy(); - copy.setCount(1); - setTestStack(copy); - } - } - - @Override - public List> getPhantomTargets(Object ingredient) { - if (!(ingredient instanceof ItemStack)) { - return Collections.emptyList(); - } - Rectangle rectangle = toRectangleBox(); - return Lists.newArrayList(new IGhostIngredientHandler.Target() { - - @NotNull - @Override - public Rectangle getArea() { - return rectangle; - } - - @Override - public void accept(@NotNull Object ingredient) { - if (ingredient instanceof ItemStack) { - putItem((ItemStack) ingredient); - } - } - }); - } -} diff --git a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java b/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java deleted file mode 100644 index fd81e80bcd7..00000000000 --- a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java +++ /dev/null @@ -1,202 +0,0 @@ -package gregtech.common.gui.widget.orefilter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.ImageWidget; -import gregtech.api.gui.widgets.WidgetGroup; -import gregtech.api.util.LocalizationUtils; -import gregtech.api.util.Position; -import gregtech.api.util.function.BooleanConsumer; -import gregtech.api.util.oreglob.OreGlob; - -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import it.unimi.dsi.fastutil.objects.Object2BooleanAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanMaps; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author brachy84 - */ -public abstract class OreFilterTestSlot extends WidgetGroup { - - private final ImageWidget match; - private final ImageWidget noMatch; - - @Nullable - private OreGlob glob; - private boolean expectedResult = true; - - @Nullable - private TextureArea slotIcon = GuiTextures.SLOT; - - @Nullable - private BooleanConsumer onMatchChange; - - private Object2BooleanMap testResult; - private MatchType matchType = MatchType.INVALID; - private boolean matchSuccess; - - private boolean initialized = false; - - private boolean matchAll; - - public OreFilterTestSlot(int xPosition, int yPosition) { - super(xPosition, yPosition, 18, 18); - this.match = new ImageWidget(18 - 5, -3, 9, 6, GuiTextures.ORE_FILTER_MATCH); - this.noMatch = new ImageWidget(18 - 5, -3, 7, 7, GuiTextures.ORE_FILTER_NO_MATCH); - addWidget(this.match); - addWidget(this.noMatch); - } - - @Override - public void initWidget() { - this.initialized = true; - updatePreview(); - super.initWidget(); - } - - public boolean isMatchSuccess() { - return matchSuccess; - } - - public OreFilterTestSlot setSlotIcon(@Nullable TextureArea slotIcon) { - this.slotIcon = slotIcon; - return this; - } - - public OreFilterTestSlot setExpectedResult(boolean expectedResult) { - this.expectedResult = expectedResult; - return this; - } - - public OreFilterTestSlot onMatchChange(@Nullable BooleanConsumer onMatchChange) { - this.onMatchChange = onMatchChange; - return this; - } - - public void setGlob(@Nullable OreGlob glob) { - if (this.glob == glob) return; - this.glob = glob; - updatePreview(); - } - - public void setMatchAll(boolean matchAll) { - if (this.matchAll == matchAll) return; - this.matchAll = matchAll; - updatePreview(); - } - - protected void updatePreview() { - if (!this.initialized) return; - Set oreDicts = getTestCandidates(); - if (oreDicts != null) { - OreGlob glob = this.glob; - if (oreDicts.isEmpty()) { - // no oredict entries - this.testResult = Object2BooleanMaps.singleton("", glob != null && glob.matches("")); - this.matchType = MatchType.NO_ORE_DICT_MATCH; - } else { - this.testResult = new Object2BooleanAVLTreeMap<>(); - for (String oreDict : oreDicts) { - boolean matches = glob != null && glob.matches(oreDict); - this.testResult.put(oreDict, matches); - } - this.matchType = MatchType.ORE_DICT_MATCH; - } - boolean success = this.matchAll; - for (var e : testResult.object2BooleanEntrySet()) { - boolean result = e.getBooleanValue(); - if (result == !this.matchAll) { - success = !this.matchAll; - break; - } - } - updateAndNotifyMatchSuccess(this.expectedResult == success); - this.match.setVisible(this.expectedResult == success); - this.noMatch.setVisible(this.expectedResult != success); - return; - } - this.testResult = Object2BooleanMaps.emptyMap(); - this.matchType = MatchType.INVALID; - updateAndNotifyMatchSuccess(false); - this.match.setVisible(false); - this.noMatch.setVisible(false); - } - - private void updateAndNotifyMatchSuccess(boolean newValue) { - if (this.matchSuccess == newValue) return; - this.matchSuccess = newValue; - if (this.onMatchChange != null) { - this.onMatchChange.apply(newValue); - } - } - - /** - * Get each test candidate for current state of test slot. An empty collection indicates that the match is for items - * without any ore dictionary entry. A {@code null} value indicates that the input state is invalid or empty. - * - * @return each test candidate for current state of test slot - */ - @Nullable - protected abstract Set getTestCandidates(); - - @Override - @SideOnly(Side.CLIENT) - public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { - Position pos = getPosition(); - if (this.slotIcon != null) { - this.slotIcon.draw(pos.x, pos.y, 18, 18); - } - - renderSlotContents(partialTicks, context); - - if (isActive() && isMouseOverElement(mouseX, mouseY)) { - GlStateManager.disableDepth(); - GlStateManager.colorMask(true, true, true, false); - drawSolidRect(getPosition().x + 1, getPosition().y + 1, 16, 16, 0x80ffffff); - GlStateManager.colorMask(true, true, true, true); - GlStateManager.enableBlend(); - } - - GlStateManager.disableDepth(); - super.drawInBackground(mouseX, mouseY, partialTicks, context); - GlStateManager.enableDepth(); - } - - protected abstract void renderSlotContents(float partialTicks, IRenderContext context); - - @Override - public void drawInForeground(int mouseX, int mouseY) { - if (isActive() && isMouseOverElement(mouseX, mouseY)) { - drawHoveringText(ItemStack.EMPTY, switch (this.matchType) { - case NO_ORE_DICT_MATCH -> Collections.singletonList(I18n.format(this.matchSuccess ? - "cover.ore_dictionary_filter.test_slot.no_oredict.matches" : - "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not")); - case ORE_DICT_MATCH -> this.testResult.object2BooleanEntrySet().stream().map( - e -> I18n.format(e.getBooleanValue() ? - "cover.ore_dictionary_filter.test_slot.matches" : - "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey())) - .collect(Collectors.toList()); - default -> Arrays.asList(LocalizationUtils.formatLines("cover.ore_dictionary_filter.test_slot.info")); - }, 300, mouseX, mouseY); - } - } - - private enum MatchType { - NO_ORE_DICT_MATCH, - ORE_DICT_MATCH, - INVALID - } -} diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index d194fedd4f5..23c6f54c761 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -26,6 +26,11 @@ import gregtech.api.util.RandomPotionEffect; import gregtech.common.ConfigHolder; import gregtech.common.blocks.MetaBlocks; +import gregtech.common.covers.filter.IFilter; +import gregtech.common.covers.filter.OreDictionaryItemFilter; +import gregtech.common.covers.filter.SimpleFluidFilter; +import gregtech.common.covers.filter.SimpleItemFilter; +import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.entities.GTBoatEntity.GTBoatType; import gregtech.common.items.behaviors.ClipboardBehavior; @@ -47,6 +52,10 @@ import gregtech.common.items.behaviors.TooltipBehavior; import gregtech.common.items.behaviors.TricorderBehavior; import gregtech.common.items.behaviors.TurbineRotorBehavior; +import gregtech.common.items.behaviors.filter.OreDictFilterUIManager; +import gregtech.common.items.behaviors.filter.SimpleFilterUIManager; +import gregtech.common.items.behaviors.filter.SimpleFluidFilterUIManager; +import gregtech.common.items.behaviors.filter.SmartFilterUIManager; import gregtech.common.items.behaviors.monitorplugin.AdvancedMonitorPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.FakeGuiPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.OnlinePicPluginBehavior; @@ -579,14 +588,18 @@ public void registerSubItems() { // Filters: ID 290-300 FLUID_FILTER = addItem(290, "fluid_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))) + .addComponents(new SimpleFluidFilterUIManager(), IFilter.factory(SimpleFluidFilter::new)); ITEM_FILTER = addItem(291, "item_filter") .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2), - new MaterialStack(Materials.Steel, M))); + new MaterialStack(Materials.Steel, M))) + .addComponents(new SimpleFilterUIManager(), IFilter.factory(SimpleItemFilter::new)); ORE_DICTIONARY_FILTER = addItem(292, "ore_dictionary_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))) + .addComponents(new OreDictFilterUIManager(), IFilter.factory(OreDictionaryItemFilter::new)); SMART_FILTER = addItem(293, "smart_item_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 3 / 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 3 / 2))) + .addComponents(new SmartFilterUIManager(), IFilter.factory(SmartItemFilter::new)); // Functional Covers: ID 301-330 COVER_MACHINE_CONTROLLER = addItem(301, "cover.controller"); diff --git a/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java new file mode 100644 index 00000000000..64fa36e7118 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java @@ -0,0 +1,55 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.api.cover.CoverWithUI; +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.mui.GTGuiTheme; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.factory.MetaItemGuiFactory; + +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; + +import java.util.List; + +public abstract class BaseFilterUIManager implements IItemBehaviour, ItemUIFactory { + + @Override + public final ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack heldItem = player.getHeldItem(hand); + if (!world.isRemote && !player.isSneaking()) { + MetaItemGuiFactory.open(player, hand); + } + if (player.isSneaking() && heldItem.hasTagCompound()) { + heldItem.setTagCompound(null); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } + + @Override + public abstract ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager); + + protected final ModularPanel createBasePanel(ItemStack stack) { + return GTGuis.createPanel(stack, 176, 188) + .child(CoverWithUI.createTitleRow(stack)); + } + + @Override + public GTGuiTheme getUITheme() { + return GTGuiTheme.COVER; + } + + @Override + public void addInformation(ItemStack itemStack, List lines) { + lines.add(I18n.format("behaviour.filter_ui_manager")); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java new file mode 100644 index 00000000000..2656db4758a --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class OreDictFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).height(160) + .child(filter.createWidgets(guiSyncManager).top(22).margin(7, 0)) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java new file mode 100644 index 00000000000..2c3b5da39cd --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SimpleFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).padding(4).height(166) + .child(filter.createWidgets(guiSyncManager).top(22).left(7)) + .child(SlotGroupWidget.playerInventory().left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java new file mode 100644 index 00000000000..df66b9c5bca --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SimpleFluidFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).padding(4).height(166) + .child(filter.createWidgets(guiSyncManager).top(22).left(7)) + .child(SlotGroupWidget.playerInventory().left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java new file mode 100644 index 00000000000..033fbb2e109 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SmartFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).height(166) + .child(filter.createWidgets(guiSyncManager).left(7).top(22)) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java index d49fb520bf1..1128819ff6d 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java @@ -144,7 +144,7 @@ protected void moveItemsInEffectRange() { double distanceX = (areaCenterPos.getX() + 0.5) - entityItem.posX; double distanceZ = (areaCenterPos.getZ() + 0.5) - entityItem.posZ; double distance = MathHelper.sqrt(distanceX * distanceX + distanceZ * distanceZ); - if (!itemFilter.testItemStack(entityItem.getItem())) { + if (!itemFilter.test(entityItem.getItem())) { continue; } if (distance >= 0.7) { diff --git a/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java b/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java new file mode 100644 index 00000000000..3bb6a3e652b --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java @@ -0,0 +1,95 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.api.value.IStringValue; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.textfield.TextFieldHandler; +import com.cleanroommc.modularui.widgets.textfield.TextFieldRenderer; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import java.util.Map; +import java.util.function.Function; + +public class HighlightedTextField extends TextFieldWidget { + + private StringSyncValue stringSyncValue; + + private final TextHighlighter highlighter; + private Runnable onUnfocus; + + public HighlightedTextField() { + this.highlighter = new TextHighlighter(this.handler); + this.renderer = this.highlighter; + this.handler.setRenderer(this.renderer); + } + + @Override + public void afterInit() { + this.highlighter.runHighlighter(getText()); + } + + /** + * Text highlighter applied only in rendering text. Only formatting characters can be inserted. + * + * @param highlightRule Consumer for text highlighter + * @return This + */ + public HighlightedTextField setHighlightRule(Function highlightRule) { + this.highlighter.setHighlightRule(highlightRule); + return getThis(); + } + + @Override + public HighlightedTextField value(IStringValue stringValue) { + this.stringSyncValue = (StringSyncValue) stringValue; + super.value(stringValue); + return getThis(); + } + + @Override + public HighlightedTextField getThis() { + return this; + } + + @Override + public void onRemoveFocus(GuiContext context) { + super.onRemoveFocus(context); + highlighter.runHighlighter(getText()); + if (isSynced()) + this.stringSyncValue.setStringValue(getText(), true, true); + onUnfocus.run(); + } + + public HighlightedTextField onUnfocus(Runnable onUnfocus) { + this.onUnfocus = onUnfocus; + return getThis(); + } + + public static final class TextHighlighter extends TextFieldRenderer { + + private Function highlightRule = string -> string; + + private Map cacheMap = new Object2ObjectOpenHashMap<>(); + + public TextHighlighter(TextFieldHandler handler) { + super(handler); + } + + public void setHighlightRule(Function highlightRule) { + this.highlightRule = highlightRule; + } + + @Override + protected float draw(String text, float x, float y) { + return super.draw(this.cacheMap.getOrDefault(text, text), x, y); + } + + public void runHighlighter(String text) { + if (this.highlightRule == null) { + return; + } + this.cacheMap.computeIfAbsent(text, string -> this.highlightRule.apply(string)); + } + } +} diff --git a/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java b/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java new file mode 100644 index 00000000000..9e16df34dfb --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java @@ -0,0 +1,42 @@ +package gregtech.common.mui.widget.orefilter; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.widgets.slot.ModularSlot; +import org.jetbrains.annotations.NotNull; + +public class ItemOreFilterTestSlot extends ModularSlot { + + OreFilterTestSlot parent; + + public ItemOreFilterTestSlot() { + super(new ItemStackHandler(1), 0, true); + } + + void setParent(OreFilterTestSlot parent) { + this.parent = parent; + } + + @Override + public void putStack(ItemStack stack) { + ItemStack testStack = getStack(); + if ((stack.isEmpty() ^ testStack.isEmpty()) || !testStack.isItemEqual(stack) || + !ItemStack.areItemStackTagsEqual(testStack, stack)) { + ItemStack copy = stack.copy(); + copy.setCount(1); + super.putStack(copy); + this.parent.updatePreview(); + } + } + + @Override + public int getSlotStackLimit() { + return 1; + } + + @Override + public int getItemStackLimit(@NotNull ItemStack stack) { + return 1; + } +} diff --git a/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java b/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java new file mode 100644 index 00000000000..1948364bbec --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java @@ -0,0 +1,144 @@ +package gregtech.common.mui.widget.orefilter; + +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.unification.OreDictUnifier; +import gregtech.api.util.function.BooleanConsumer; +import gregtech.api.util.oreglob.OreGlob; +import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.widgets.ItemSlot; +import it.unimi.dsi.fastutil.objects.Object2BooleanAVLTreeMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * @author brachy84 + */ +public class OreFilterTestSlot extends ItemSlot { + + private final ItemOreFilterTestSlot slot; + private Supplier globSupplier = ImpossibleOreGlob::getInstance; + @Nullable + private BooleanConsumer onMatchChange; + private final Object2BooleanMap testResult = new Object2BooleanAVLTreeMap<>(); + private MatchType matchType = MatchType.INVALID; + private boolean matchSuccess; + private boolean matchAll; + + public OreFilterTestSlot() { + this.slot = new ItemOreFilterTestSlot(); + this.slot.setParent(this); + slot(this.slot); + tooltipBuilder(tooltip -> { + if (!isEnabled()) return; + tooltip.addDrawableLines(switch (this.matchType) { + case NO_ORE_DICT_MATCH -> Collections.singletonList(IKey.lang(this.matchSuccess ? + "cover.ore_dictionary_filter.test_slot.no_oredict.matches" : + "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not")); + case ORE_DICT_MATCH -> this.testResult.object2BooleanEntrySet() + .stream().map(e -> IKey.lang(e.getBooleanValue() ? + "cover.ore_dictionary_filter.test_slot.matches" : + "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey())) + .collect(Collectors.toList()); + default -> Collections.singletonList(IKey.lang("cover.ore_dictionary_filter.test_slot.info")); + }); + }); + } + + public OreFilterTestSlot setGlobSupplier(Supplier supplier) { + this.globSupplier = supplier; + this.updatePreview(); + return getThis(); + } + + @Override + public OreFilterTestSlot getThis() { + return this; + } + + public boolean isMatchSuccess() { + return matchSuccess; + } + + public OreFilterTestSlot onMatchChange(@Nullable BooleanConsumer onMatchChange) { + this.onMatchChange = onMatchChange; + return getThis(); + } + + public void setMatchAll(boolean matchAll) { + if (this.matchAll == matchAll) return; + this.matchAll = matchAll; + updatePreview(); + } + + public void updatePreview() { + Set oreDicts = getTestCandidates(); + this.testResult.clear(); + if (oreDicts == null) { + this.matchType = MatchType.INVALID; + updateAndNotifyMatchSuccess(false); + return; + } + OreGlob glob = this.globSupplier.get(); + int success = 0; + if (oreDicts.isEmpty()) { + // no oredict entries + this.testResult.put("", glob != null && glob.matches("")); + this.matchType = MatchType.NO_ORE_DICT_MATCH; + } else { + for (String oreDict : oreDicts) { + boolean matches = glob != null && glob.matches(oreDict); + if (matches) success++; + this.testResult.put(oreDict, matches); + } + this.matchType = MatchType.ORE_DICT_MATCH; + } + updateAndNotifyMatchSuccess(this.matchAll ? success == testResult.size() : success > 0); + this.tooltip().markDirty(); + } + + @Override + public void draw(GuiContext context, WidgetTheme widgetTheme) { + super.draw(context, widgetTheme); + if (this.matchSuccess) { + GTGuiTextures.OREDICT_MATCH + .draw(context, 12, -2, 9, 6, widgetTheme); + } else if (testResult.size() > 0) { + GTGuiTextures.OREDICT_NO_MATCH + .draw(context, 12, -3, 7, 7, widgetTheme); + } + } + + private void updateAndNotifyMatchSuccess(boolean newValue) { + if (this.matchSuccess == newValue) return; + this.matchSuccess = newValue; + if (this.onMatchChange != null) { + this.onMatchChange.apply(newValue); + } + } + + /** + * Get each test candidate for current state of test slot. An empty collection indicates that the match is for items + * without any ore dictionary entry. A {@code null} value indicates that the input state is invalid or empty. + * + * @return each test candidate for current state of test slot + */ + @Nullable + protected Set getTestCandidates() { + return this.slot.getStack().isEmpty() ? null : OreDictUnifier.getOreDictionaryNames(this.slot.getStack()); + } + + private enum MatchType { + NO_ORE_DICT_MATCH, + ORE_DICT_MATCH, + INVALID + } +} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index a2313f82398..20967af87e4 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -6,7 +6,11 @@ import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; -import gregtech.common.covers.*; +import gregtech.common.covers.CoverConveyor; +import gregtech.common.covers.CoverItemFilter; +import gregtech.common.covers.CoverRoboticArm; +import gregtech.common.covers.DistributionMode; +import gregtech.common.covers.ItemFilterMode; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; @@ -364,15 +368,18 @@ public Cover getCoverOnNeighbour(TileEntityItemPipe itemPipe, EnumFacing facing) public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, ItemStack stack, boolean simulate, int allowed, boolean ignoreLimit) { - int rate; + var matched = arm.getItemFilterContainer().match(stack); boolean isStackSpecific = false; - Object index = arm.getItemFilterContainer().matchItemStack(stack); - if (index instanceof Integer) { - rate = arm.getItemFilterContainer().getSlotTransferLimit(index); + int rate, count; + + if (matched.isMatched()) { + int index = matched.getFilterIndex(); + rate = arm.getItemFilterContainer().getTransferLimit(index); isStackSpecific = true; - } else - rate = arm.getItemFilterContainer().getTransferStackSize(); - int count; + } else { + rate = arm.getItemFilterContainer().getTransferSize(); + } + switch (arm.getTransferMode()) { case TRANSFER_ANY: return insert(handler, stack, simulate, allowed, ignoreLimit); @@ -405,7 +412,7 @@ public static int countStack(IItemHandler handler, ItemStack stack, CoverRobotic ItemStack slot = handler.getStackInSlot(i); if (slot.isEmpty()) continue; if (isStackSpecific ? ItemStackHashStrategy.comparingAllButCount().equals(stack, slot) : - arm.getItemFilterContainer().testItemStack(slot)) { + arm.getItemFilterContainer().test(slot)) { count += slot.getCount(); } } diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java index 46eeb3e8335..c05116355f7 100644 --- a/src/main/java/gregtech/core/CoreModule.java +++ b/src/main/java/gregtech/core/CoreModule.java @@ -43,7 +43,6 @@ import gregtech.common.command.CommandShaders; import gregtech.common.command.worldgen.CommandWorldgen; import gregtech.common.covers.CoverBehaviors; -import gregtech.common.covers.filter.FilterTypeRegistry; import gregtech.common.covers.filter.oreglob.impl.OreGlobParser; import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; @@ -255,7 +254,6 @@ public void init(FMLInitializationEvent event) { WorldGenRegistry.INSTANCE.initializeRegistry(); LootTableHelper.initialize(); - FilterTypeRegistry.init(); /* Start Cover Definition Registration */ COVER_REGISTRY.unfreeze(); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java index 6656fcc9d7e..0aebf88036a 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java @@ -10,6 +10,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.common.capabilities.Capability; @@ -57,22 +58,25 @@ protected void addProbeInfo(@NotNull CoverHolder capability, @NotNull IProbeInfo * @param conveyor the conveyor to get data from */ private static void conveyorInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverConveyor conveyor) { - String rateUnit = " {*cover.conveyor.transfer_rate*}"; + String rateUnit = lang("cover.conveyor.transfer_rate"); if (conveyor instanceof CoverItemVoiding) { itemVoidingInfo(probeInfo, (CoverItemVoiding) conveyor); - } else if (!(conveyor instanceof CoverRoboticArm) || - ((CoverRoboticArm) conveyor).getTransferMode() == TransferMode.TRANSFER_ANY) { + } else if (!(conveyor instanceof CoverRoboticArm arm) || + arm.getTransferMode() == TransferMode.TRANSFER_ANY) { // only display the regular rate if the cover does not have a specialized rate - transferRateText(probeInfo, conveyor.getConveyorMode(), rateUnit, conveyor.getTransferRate()); + transferRateText(probeInfo, conveyor.getConveyorMode(), " " + rateUnit, conveyor.getTransferRate()); } ItemFilterContainer filter = conveyor.getItemFilterContainer(); if (conveyor instanceof CoverRoboticArm roboticArm) { - transferModeText(probeInfo, roboticArm.getTransferMode(), rateUnit, filter.getTransferStackSize(), - filter.getFilterWrapper().getItemFilter() != null); + if (roboticArm.getTransferMode() != TransferMode.TRANSFER_ANY) + rateUnit = lang("cover.robotic_arm.exact"); + + transferModeText(probeInfo, roboticArm.getTransferMode(), rateUnit, + filter.getTransferSize(), filter.hasFilter()); } - itemFilterText(probeInfo, filter.getFilterWrapper().getItemFilter()); + itemFilterText(probeInfo, filter.getFilter()); } /** @@ -82,13 +86,13 @@ private static void conveyorInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverCo * @param voiding the voiding cover to get data from */ private static void itemVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverItemVoiding voiding) { - String unit = " {*gregtech.top.unit.items*}"; + String unit = lang("gregtech.top.unit.items"); ItemFilterContainer container = voiding.getItemFilterContainer(); if (voiding instanceof CoverItemVoidingAdvanced advanced) { VoidingMode mode = advanced.getVoidingMode(); - voidingText(probeInfo, mode, unit, container.getTransferStackSize(), - container.getFilterWrapper().getItemFilter() != null); + voidingText(probeInfo, mode, unit, container.getTransferSize(), + container.hasFilter() && !container.isBlacklistFilter()); } } @@ -99,12 +103,14 @@ private static void itemVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cove * @param pump the pump to get data from */ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump pump) { - String rateUnit = IProbeInfo.STARTLOC + pump.getBucketMode().getName() + IProbeInfo.ENDLOC; + String rateUnit = lang(pump.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "cover.bucket.mode.bucket_rate" : + "cover.bucket.mode.milli_bucket_rate"); if (pump instanceof CoverFluidVoiding) { fluidVoidingInfo(probeInfo, (CoverFluidVoiding) pump); - } else if (!(pump instanceof CoverFluidRegulator) || - ((CoverFluidRegulator) pump).getTransferMode() == TransferMode.TRANSFER_ANY) { + } else if (!(pump instanceof CoverFluidRegulator regulator) || + regulator.getTransferMode() == TransferMode.TRANSFER_ANY) { // do not display the regular rate if the cover has a specialized rate transferRateText(probeInfo, pump.getPumpMode(), " " + rateUnit, pump.getBucketMode() == CoverPump.BucketMode.BUCKET ? pump.getTransferRate() / 1000 : @@ -113,10 +119,15 @@ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump p FluidFilterContainer filter = pump.getFluidFilterContainer(); if (pump instanceof CoverFluidRegulator regulator) { - transferModeText(probeInfo, regulator.getTransferMode(), rateUnit, regulator.getTransferAmount(), - filter.getFilterWrapper().getFluidFilter() != null); + if (regulator.getTransferMode() != TransferMode.TRANSFER_ANY) + rateUnit = lang(regulator.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "gregtech.top.unit.fluid_buckets" : + "gregtech.top.unit.fluid_milibuckets"); + + transferModeText(probeInfo, regulator.getTransferMode(), rateUnit, regulator + .getFluidFilterContainer().getTransferSize(), filter.hasFilter() && !filter.isBlacklistFilter()); } - fluidFilterText(probeInfo, filter.getFilterWrapper().getFluidFilter()); + fluidFilterText(probeInfo, filter.getFilter()); } /** @@ -126,8 +137,10 @@ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump p * @param voiding the voiding cover to get data from */ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverFluidVoiding voiding) { - String unit = voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? " {*gregtech.top.unit.fluid_buckets*}" : - " {*gregtech.top.unit.fluid_milibuckets*}"; + String unit = lang(voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "gregtech.top.unit.fluid_buckets" : + "gregtech.top.unit.fluid_milibuckets"); + var container = voiding.getFluidFilterContainer(); if (voiding instanceof CoverFluidVoidingAdvanced advanced) { VoidingMode mode = advanced.getVoidingMode(); @@ -135,7 +148,7 @@ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cov voidingText(probeInfo, mode, unit, voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? advanced.getTransferAmount() / 1000 : advanced.getTransferAmount(), - voiding.getFluidFilterContainer().getFilterWrapper().getFluidFilter() != null); + container.hasFilter() && !container.isBlacklistFilter()); } } @@ -147,7 +160,7 @@ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cov */ private static void itemFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverItemFilter itemFilter) { filterModeText(probeInfo, itemFilter.getFilterMode()); - itemFilterText(probeInfo, itemFilter.getItemFilter().getItemFilter()); + itemFilterText(probeInfo, itemFilter.getFilter()); } /** @@ -158,7 +171,7 @@ private static void itemFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull Cover */ private static void fluidFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverFluidFilter fluidFilter) { filterModeText(probeInfo, fluidFilter.getFilterMode()); - fluidFilterText(probeInfo, fluidFilter.getFluidFilter().getFluidFilter()); + fluidFilterText(probeInfo, fluidFilter.getFilter()); } /** @@ -168,12 +181,13 @@ private static void fluidFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull Cove * @param enderFluidLink the ender fluid link cover to get data from */ private static void enderFluidLinkInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverEnderFluidLink enderFluidLink) { - transferRateText(probeInfo, enderFluidLink.getPumpMode(), " {*cover.bucket.mode.milli_bucket*}", + transferRateText(probeInfo, enderFluidLink.getPumpMode(), " " + lang("cover.bucket.mode.milli_bucket_rate"), enderFluidLink.isIOEnabled() ? CoverEnderFluidLink.TRANSFER_RATE : 0); - fluidFilterText(probeInfo, enderFluidLink.getFluidFilterContainer().getFilterWrapper().getFluidFilter()); + fluidFilterText(probeInfo, enderFluidLink.getFluidFilterContainer().getFilter()); if (!enderFluidLink.getColorStr().isEmpty()) { - probeInfo.text(TextStyleClass.INFO + "{*gregtech.top.link_cover.color*} " + enderFluidLink.getColorStr()); + probeInfo.text( + TextStyleClass.INFO + lang("gregtech.top.link_cover.color") + " " + enderFluidLink.getColorStr()); } } @@ -187,7 +201,8 @@ private static void enderFluidLinkInfo(@NotNull IProbeInfo probeInfo, @NotNull C */ private static void transferRateText(@NotNull IProbeInfo probeInfo, @NotNull IIOMode mode, @NotNull String rateUnit, int rate) { - String modeText = mode.isImport() ? "{*gregtech.top.mode.import*} " : "{*gregtech.top.mode.export*} "; + String modeText = mode.isImport() ? lang("gregtech.top.mode.import") : lang("gregtech.top.mode.export"); + modeText += " "; probeInfo.text(TextStyleClass.OK + modeText + TextStyleClass.LABEL + TextFormattingUtil.formatNumbers(rate) + rateUnit); } @@ -197,15 +212,15 @@ private static void transferRateText(@NotNull IProbeInfo probeInfo, @NotNull IIO * * @param probeInfo the info to add the text to * @param mode the transfer mode of the cover - * @param rateUnit the unit of what is transferred * @param rate the transfer rate of the mode * @param hasFilter whether the cover has a filter installed */ private static void transferModeText(@NotNull IProbeInfo probeInfo, @NotNull TransferMode mode, @NotNull String rateUnit, int rate, boolean hasFilter) { - String text = TextStyleClass.OK + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC; + String text = TextStyleClass.OK + lang(mode.getName()); if (!hasFilter && mode != TransferMode.TRANSFER_ANY) - text += TextStyleClass.LABEL + " " + TextFormattingUtil.formatNumbers(rate) + rateUnit; + text += TextStyleClass.LABEL + " " + TextFormattingUtil.formatNumbers(rate) + " " + rateUnit; + probeInfo.text(text); } @@ -220,45 +235,49 @@ private static void transferModeText(@NotNull IProbeInfo probeInfo, @NotNull Tra */ private static void voidingText(@NotNull IProbeInfo probeInfo, @NotNull VoidingMode mode, @NotNull String unit, int amount, boolean hasFilter) { - String text = TextFormatting.RED + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC; - if (mode != VoidingMode.VOID_ANY && !hasFilter) text += " " + TextFormattingUtil.formatNumbers(amount) + unit; + String text = TextFormatting.RED + lang(mode.getName()); + if (mode != VoidingMode.VOID_ANY && !hasFilter) + text += " " + TextFormattingUtil.formatNumbers(amount) + " " + unit; probeInfo.text(text); } /** - * Displays text for {@link IFilterMode} covers + * Displays text for {@link net.minecraft.util.IStringSerializable} covers * * @param probeInfo the info to add the text to * @param mode the filter mode of the cover */ - private static void filterModeText(@NotNull IProbeInfo probeInfo, @NotNull IFilterMode mode) { - probeInfo.text(TextStyleClass.WARNING + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC); + private static void filterModeText(@NotNull IProbeInfo probeInfo, @NotNull IStringSerializable mode) { + probeInfo.text(TextStyleClass.WARNING + lang(mode.getName())); } /** - * Displays text for {@link ItemFilter} covers + * Displays text for {@link BaseFilter} item covers * * @param probeInfo the info to add the text to * @param filter the filter to display info from */ - private static void itemFilterText(@NotNull IProbeInfo probeInfo, @Nullable ItemFilter filter) { - String label = TextStyleClass.INFO + "{*gregtech.top.filter.label*} "; + private static void itemFilterText(@NotNull IProbeInfo probeInfo, @Nullable BaseFilter filter) { + String label = TextStyleClass.INFO + lang("gregtech.top.filter.label"); if (filter instanceof OreDictionaryItemFilter) { String expression = ((OreDictionaryItemFilter) filter).getExpression(); if (!expression.isEmpty()) probeInfo.text(label + expression); - } else if (filter instanceof SmartItemFilter) { - probeInfo.text(label + IProbeInfo.STARTLOC + ((SmartItemFilter) filter).getFilteringMode().getName() + - IProbeInfo.ENDLOC); + } else if (filter instanceof SmartItemFilter smartItemFilter) { + probeInfo.text(label + lang(smartItemFilter.getFilteringMode().getName())); } } /** - * Displays text for {@link FluidFilter} covers + * Displays text for {@link BaseFilter} fluid covers * * @param probeInfo the info to add the text to * @param filter the filter to display info from */ - private static void fluidFilterText(@NotNull IProbeInfo probeInfo, @Nullable FluidFilter filter) { + private static void fluidFilterText(@NotNull IProbeInfo probeInfo, @Nullable BaseFilter filter) { // TODO If more unique fluid filtration is added, providers for it go here } + + private static String lang(String lang) { + return IProbeInfo.STARTLOC + lang + IProbeInfo.ENDLOC; + } } diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index cd7b866c272..67a29315718 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -1405,6 +1405,16 @@ private static void registerNBTRemoval() { ModHandler.addShapelessNBTClearingRecipe("data_module_nbt", TOOL_DATA_MODULE.getStackForm(), TOOL_DATA_MODULE.getStackForm()); + // Filters + ModHandler.addShapelessNBTClearingRecipe("clear_item_filter", + ITEM_FILTER.getStackForm(), ITEM_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_fluid_filter", + FLUID_FILTER.getStackForm(), FLUID_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_smart_filter", + SMART_FILTER.getStackForm(), SMART_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_oredict_filter", + ORE_DICTIONARY_FILTER.getStackForm(), ORE_DICTIONARY_FILTER); + // Jetpacks ModHandler.addShapelessRecipe("fluid_jetpack_clear", SEMIFLUID_JETPACK.getStackForm(), SEMIFLUID_JETPACK.getStackForm()); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 6fc2ebe2f39..d54a69b3e44 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -822,6 +822,7 @@ metaitem.fluid_filter.name=Fluid Filter metaitem.fluid_filter.tooltip=Filters §fFluid§7 I/O as §fCover§7./nCan be used as an §fElectric Pump§7 and §fFluid Regulator§7 upgrade. metaitem.smart_item_filter.name=Smart Item Filter metaitem.smart_item_filter.tooltip=Filters §fItem§7 I/O with §fMachine Recipes§7 as §fCover§7./nCan be used as a §fConveyor Module§7 and §fRobotic Arm§7 upgrade. +behaviour.filter_ui_manager=§fRight-Click§7 to configure, §fShift Right-Click§7 to clear configuration metaitem.cover.controller.name=Machine Controller metaitem.cover.controller.tooltip=Turns Machines §fON/OFF§7 as §fCover§7. @@ -1178,7 +1179,9 @@ cover.filter.blacklist.disabled=Whitelist cover.filter.blacklist.enabled=Blacklist cover.ore_dictionary_filter.title=Ore Dictionary Filter -cover.ore_dictionary_filter.info=§bAccepts complex expressions/n§6a & b§r = AND/n§6a | b§r = OR/n§6a ^ b§r = XOR/n§6! abc§r = NOT/n§6( abc )§r for grouping/n§6*§r for wildcard (i.e. 0 or more characters)/n§6?§r for any 1 character/n§6()§r for matching empty entry (including items with no ore dictionary)/n§bExample:/n§6dust*Gold | (plate* & !*Double*)/nWill match all gold dusts of all sizes or all plates, but not double plates +cover.ore_dictionary_filter.info=§bAccepts complex expressions\n§6a & b§r = AND\n§6a | b§r = OR\n§6a ^ b§r = XOR\n§6! abc§r = NOT\n§6( abc )§r for grouping\n§6*§r for wildcard (i.e. 0 or more characters)\n§6?§r for any 1 character\n§6()§r for matching empty entry (including items with no ore dictionary)\n§bExample:\n§6dust*Gold | (plate* & !*Double*)\nWill match all gold dusts of all sizes or all plates, but not double plates +cover.ore_dictionary_filter.match_all=Match All: %s +cover.ore_dictionary_filter.case_sensitive=Case Sensitive: %s cover.ore_dictionary_filter.test_slot.info=Insert a item to test if it matches the filter expression cover.ore_dictionary_filter.test_slot.matches=§a* %s cover.ore_dictionary_filter.test_slot.matches_not=§c* %s @@ -1243,6 +1246,7 @@ cover.fluid_filter.mode.filter_drain=Filter Drain cover.fluid_filter.mode.filter_both=Filter Fill & Drain cover.item_filter.title=Item Filter +cover.filter.mode.title=Filter Mode cover.filter.mode.filter_insert=Filter Insert cover.filter.mode.filter_extract=Filter Extract cover.filter.mode.filter_both=Filter Insert/Extract @@ -1250,9 +1254,11 @@ cover.item_filter.ignore_damage.enabled=Ignore Damage cover.item_filter.ignore_damage.disabled=Respect Damage cover.item_filter.ignore_nbt.enabled=Ignore NBT cover.item_filter.ignore_nbt.disabled=Respect NBT +cover.item_filter.config_amount=Scroll wheel up increases amount, down decreases.\nShift[§6x4§r], Ctrl[§ex16§r], Alt[§ax64§r]\nRight click increases amount, left click decreases.\nShift Left-Click to clear cover.voiding.voiding_mode.void_any=Void Matching cover.voiding.voiding_mode.void_overflow=Void Overflow +cover.voiding.voiding_mode=Voiding Mode cover.voiding.voiding_mode.description=§eVoid Matching§r will void anything matching the filter. /n§eVoid Overflow§r will void anything matching the filter, up to the specified amount. cover.fluid.voiding.title=Fluid Voiding Settings cover.fluid.voiding.advanced.title=Advanced Fluid Voiding Settings @@ -1273,13 +1279,18 @@ cover.smart_item_filter.filtering_mode.centrifuge=Centrifuge cover.smart_item_filter.filtering_mode.sifter=Sifter cover.smart_item_filter.filtering_mode.description=Select Machine this Smart Filter will use for filtering./nIt will automatically pick right portions of items for robotic arm. +cover.generic.transfer_mode=Transfer Mode +cover.generic.manual_io=Manual IO Mode +cover.generic.io=IO Mode +cover.pump.mode=Pump Mode cover.conveyor.title=Conveyor Cover Settings (%s) cover.conveyor.transfer_rate=§7items/sec cover.conveyor.mode.export=Mode: Export cover.conveyor.mode.import=Mode: Import -cover.conveyor.distribution.round_robin_enhanced=Distribution Mode/n§bEnhanced Round Robin§r/n§7Splits items equally to all inventories -cover.conveyor.distribution.round_robin=Distribution Mode/n§bRound Robin§r with Priority/n§7Tries to split items equally to inventories -cover.conveyor.distribution.first_insert=Distribution Mode/n§bFirst Insert§r/n§7Will insert into the first inventory it finds +cover.conveyor.distribution.name=Distribution Mode +cover.conveyor.distribution.round_robin_enhanced=§bEnhanced Round Robin§r\n§7Splits items equally to all inventories +cover.conveyor.distribution.round_robin=§bRound Robin§r with Priority\n§7Tries to split items equally to inventories +cover.conveyor.distribution.first_insert=§bFirst Insert§r\n§7Will insert into the first inventory it finds cover.conveyor.blocks_input.enabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§aEnabled cover.conveyor.blocks_input.disabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§cDisabled cover.universal.manual_import_export.mode.disabled=Manual I/O: Disabled @@ -1290,6 +1301,7 @@ cover.conveyor.item_filter.title=Item Filter cover.conveyor.ore_dictionary.title=Ore Dictionary Name cover.conveyor.ore_dictionary.title2=(use * for wildcard) cover.robotic_arm.title=Robotic Arm Settings (%s) +cover.robotic_arm.exact=§7items cover.robotic_arm.transfer_mode.transfer_any=Transfer Any cover.robotic_arm.transfer_mode.transfer_exact=Supply Exact cover.robotic_arm.transfer_mode.keep_exact=Keep Exact @@ -1300,8 +1312,12 @@ cover.pump.transfer_rate=%s cover.pump.mode.export=Mode: Export cover.pump.mode.import=Mode: Import cover.pump.fluid_filter.title=Fluid Filter -cover.bucket.mode.bucket=kL/s -cover.bucket.mode.milli_bucket=L/s +cover.bucket.mode.bucket=Bucket Mode: kL +cover.bucket.mode.milli_bucket=Bucket Mode: L +cover.bucket.mode.bucket_rate=kL/s +cover.bucket.mode.bucket_exact=kL +cover.bucket.mode.milli_bucket_rate=L/s +cover.bucket.mode.milli_bucket_exact=L cover.fluid_regulator.title=Fluid Regulator Settings (%s) cover.fluid_regulator.transfer_mode.description=§eTransfer Any§r - in this mode, cover will transfer as many fluids matching its filter as possible./n§eSupply Exact§r - in this mode, cover will supply fluids in portions specified in the window underneath this button. If amount of fluids is less than portion size, fluids won't be moved./n§eKeep Exact§r - in this mode, cover will keep specified amount of fluids in the destination inventory, supplying additional amount of fluids if required./n§7Tip: shift click will multiply increase/decrease amounts by 10 and ctrl click will multiply by 100. cover.fluid_regulator.supply_exact=Supply Exact: %s @@ -1324,7 +1340,7 @@ cover.machine_controller.disable_with_redstone=Disable with Redstone cover.ender_fluid_link.title=Ender Fluid Link cover.ender_fluid_link.iomode.enabled=I/O Enabled cover.ender_fluid_link.iomode.disabled=I/O Disabled -cover.ender_fluid_link.private.tooltip.disabled=Switch to private tank mode/nPrivate mode uses the player who originally placed the cover +cover.ender_fluid_link.private.tooltip.disabled=Switch to private tank mode\nPrivate mode uses the player who originally placed the cover cover.ender_fluid_link.private.tooltip.enabled=Switch to public tank mode cover.ender_fluid_link.incomplete_hex=Inputted color is incomplete!/nIt will be applied once complete (all 8 hex digits)/nClosing the gui will lose edits! diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png new file mode 100644 index 00000000000..0c2a1ac6212 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png new file mode 100644 index 00000000000..0f9c95e8b68 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/filter_settings_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/filter_settings_overlay.png new file mode 100644 index 00000000000..31b8cdb6ce8 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/filter_settings_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/fluid_transfer_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/fluid_transfer_mode_overlay.png new file mode 100644 index 00000000000..6fe690f9fbb Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/fluid_transfer_mode_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png new file mode 100644 index 00000000000..a8f8bef7a54 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png new file mode 100644 index 00000000000..9364d84544d Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/voiding_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/voiding_mode_overlay.png new file mode 100644 index 00000000000..d948e2c551c Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/overlay/voiding_mode_overlay.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png b/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png index 86f6a27bd53..9dbdac4862f 100644 Binary files a/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png and b/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png differ