From 9af741164c5b59c4d884aba48ebeab7db5442d63 Mon Sep 17 00:00:00 2001 From: miozune Date: Sun, 28 May 2023 18:21:42 +0900 Subject: Add new mode for void protection & implement it for more multis (#2024) * Void protection improvements * Rename methods: isXXXButtonEnabled -> supportsXXX * Adjust texture for forbidden * Add MultiBlockFeatureSupportDumpers * Fix oversight in PCBFactory * Revert void protection support for PA * Rename class: ControllerWithButtons -> ControllerWithOptionalFeatures --- src/main/java/gregtech/api/enums/GT_Values.java | 2 +- src/main/java/gregtech/api/enums/VoidingMode.java | 78 +++++ .../gregtech/api/gui/modularui/GT_UITextures.java | 28 +- .../modularui/ControllerWithOptionalFeatures.java | 304 ++++++++++++++++ .../api/logic/ComplexParallelProcessingLogic.java | 16 +- .../api/metatileentity/BaseTileEntity.java | 1 + .../GT_MetaTileEntity_MultiBlockBase.java | 383 ++++++++------------- .../multiblock/base/ComplexParallelController.java | 12 +- .../multiblock/base/Controller.java | 262 ++++---------- .../java/gregtech/api/util/GT_ParallelHelper.java | 49 ++- .../gregtech/api/util/VoidProtectionHelper.java | 48 ++- .../multi/GT_MetaTileEntity_AssemblyLine.java | 7 + .../multi/GT_MetaTileEntity_DistillationTower.java | 6 + .../GT_MetaTileEntity_ElectricBlastFurnace.java | 8 +- .../multi/GT_MetaTileEntity_FusionComputer.java | 6 + .../GT_MetaTileEntity_ImplosionCompressor.java | 7 +- .../GT_MetaTileEntity_LargeChemicalReactor.java | 7 +- .../multi/GT_MetaTileEntity_NanoForge.java | 9 +- .../multi/GT_MetaTileEntity_OilCracker.java | 6 + .../multi/GT_MetaTileEntity_OilDrillBase.java | 8 +- .../GT_MetaTileEntity_OreDrillingPlantBase.java | 9 +- .../multi/GT_MetaTileEntity_PCBFactory.java | 8 +- .../multi/GT_MetaTileEntity_PlasmaForge.java | 7 + .../multi/GT_MetaTileEntity_ProcessingArray.java | 14 +- .../multi/GT_MetaTileEntity_PyrolyseOven.java | 8 +- .../GT_MetaTileEntity_TranscendentPlasmaMixer.java | 7 + .../multi/GT_MetaTileEntity_VacuumFreezer.java | 6 + .../machines/multiblock/AdvChemicalReactor.java | 5 +- .../tileentities/machines/multiblock/CokeOven.java | 2 +- .../storage/GT_MetaTileEntity_DigitalTankBase.java | 4 +- src/main/java/gregtech/nei/NEI_GT_Config.java | 8 + .../nei/dumper/BatchModeSupportDumper.java | 10 + .../nei/dumper/InputSeparationSupportDumper.java | 10 + .../nei/dumper/MultiBlockFeatureSupportDumper.java | 46 +++ .../nei/dumper/RecipeLockingSupportDumper.java | 10 + .../nei/dumper/VoidProtectionSupportDumper.java | 10 + 36 files changed, 909 insertions(+), 502 deletions(-) create mode 100644 src/main/java/gregtech/api/enums/VoidingMode.java create mode 100644 src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java create mode 100644 src/main/java/gregtech/nei/dumper/BatchModeSupportDumper.java create mode 100644 src/main/java/gregtech/nei/dumper/InputSeparationSupportDumper.java create mode 100644 src/main/java/gregtech/nei/dumper/MultiBlockFeatureSupportDumper.java create mode 100644 src/main/java/gregtech/nei/dumper/RecipeLockingSupportDumper.java create mode 100644 src/main/java/gregtech/nei/dumper/VoidProtectionSupportDumper.java (limited to 'src/main/java') diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index 3d4180667a..d494c5b64c 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -343,7 +343,7 @@ public class GT_Values { UPGRADE_TANKS_COUNT = "gt.tankcount.upg", // Int UPGRADE_TANKS_PREFIX = "gt.tank.upg", // NBT Tag SEPARATE_INPUTS = "gt.separate.inputs", // Boolean - VOID_EXCESS = "gt.void.excess", // Boolean + VOIDING_MODE = "gt.voiding.mode", // String BATCH_MODE = "gt.batch.mode", // Boolean RECIPE_LOCK = "gt.recipe.lock", // Boolean diff --git a/src/main/java/gregtech/api/enums/VoidingMode.java b/src/main/java/gregtech/api/enums/VoidingMode.java new file mode 100644 index 0000000000..47f837daac --- /dev/null +++ b/src/main/java/gregtech/api/enums/VoidingMode.java @@ -0,0 +1,78 @@ +package gregtech.api.enums; + +import javax.annotation.Nonnull; + +import com.gtnewhorizons.modularui.api.drawable.UITexture; + +import gregtech.api.gui.modularui.GT_UITextures; + +public enum VoidingMode { + + /** + * Voids nothing, protects both item and fluid + */ + VOID_NONE(true, true, GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_NONE, "none"), + /** + * Voids item, protects fluid + */ + VOID_ITEM(false, true, GT_UITextures.BUTTON_STANDARD_PRESSED, GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ITEM, + "item"), + /** + * Voids fluid, protects item + */ + VOID_FLUID(true, false, GT_UITextures.BUTTON_STANDARD_PRESSED, GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_FLUID, + "fluid"), + /** + * Voids all, protects nothing + */ + VOID_ALL(false, false, GT_UITextures.BUTTON_STANDARD_PRESSED, GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ALL, "all"); + + public final boolean protectItem; + public final boolean protectFluid; + public final UITexture buttonTexture; + public final UITexture buttonOverlay; + public final String name; + + VoidingMode(boolean protectItem, boolean protectFluid, UITexture buttonTexture, UITexture buttonOverlay, + String name) { + this.protectItem = protectItem; + this.protectFluid = protectFluid; + this.buttonTexture = buttonTexture; + this.buttonOverlay = buttonOverlay; + this.name = name; + } + + public String getTransKey() { + return "GT5U.gui.button.voiding_mode_" + name; + } + + public VoidingMode next() { + return values()[(ordinal() + 1) % values().length]; + } + + public VoidingMode previous() { + return values()[(ordinal() + values().length - 1) % values().length]; + } + + /** + * Do not use this for loading mode from TEs, to prevent mode being shifted when new mode is added. + */ + @Nonnull + public static VoidingMode fromOrdinal(int ordinal) { + if (ordinal >= 0 && ordinal < values().length) { + return values()[ordinal]; + } + return VOID_NONE; + } + + @Nonnull + public static VoidingMode fromName(String name) { + for (VoidingMode mode : values()) { + if (mode.name.equals(name)) { + return mode; + } + } + return VOID_NONE; + } + +} diff --git a/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java b/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java index e8c9f192a6..8dda90a630 100644 --- a/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java +++ b/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java @@ -220,6 +220,8 @@ public class GT_UITextures { public static final UITexture BUTTON_STANDARD = AdaptableUITexture .of(GregTech.ID, "gui/button/standard", 18, 18, 1); + public static final UITexture BUTTON_STANDARD_PRESSED = AdaptableUITexture + .of(GregTech.ID, "gui/button/standard_pressed", 18, 18, 1); public static final UITexture BUTTON_STANDARD_DISABLED = AdaptableUITexture .of(GregTech.ID, "gui/button/standard_disabled", 18, 18, 1); public static final UITexture BUTTON_STANDARD_TOGGLE = AdaptableUITexture @@ -242,14 +244,14 @@ public class GT_UITextures { .fullImage(GregTech.ID, "gui/overlay_button/power_switch_on"); public static final UITexture OVERLAY_BUTTON_POWER_SWITCH_OFF = UITexture .fullImage(GregTech.ID, "gui/overlay_button/power_switch_off"); - public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ON = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_excess_on"); - public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_excess_on_disabled"); - public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_OFF = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_excess_off"); - public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_excess_off_disabled"); + public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_NONE = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/void_excess_none"); + public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ITEM = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/void_excess_item"); + public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_FLUID = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/void_excess_fluid"); + public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ALL = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/void_excess_all"); public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_ON = UITexture .fullImage(GregTech.ID, "gui/overlay_button/input_separation_on"); public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED = UITexture @@ -274,6 +276,8 @@ public class GT_UITextures { .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_off"); public static final UITexture OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED = UITexture .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_off_disabled"); + public static final UITexture OVERLAY_BUTTON_FORBIDDEN = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/forbidden"); public static final UITexture OVERLAY_BUTTON_DOWN_TIERING_ON = UITexture .fullImage(GregTech.ID, "gui/overlay_button/down_tiering_on"); public static final UITexture OVERLAY_BUTTON_DOWN_TIERING_OFF = UITexture @@ -342,10 +346,10 @@ public class GT_UITextures { public static final UITexture OVERLAY_BUTTON_LOCK = UITexture.fullImage(GregTech.ID, "gui/overlay_button/lock"); public static final UITexture OVERLAY_BUTTON_INPUT_FROM_OUTPUT_SIDE = UITexture .fullImage(GregTech.ID, "gui/overlay_button/input_from_output_side"); - public static final UITexture OVERLAY_BUTTON_VOID_EXCESS = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_excess"); - public static final UITexture OVERLAY_BUTTON_VOID_ALL = UITexture - .fullImage(GregTech.ID, "gui/overlay_button/void_all"); + public static final UITexture OVERLAY_BUTTON_TANK_VOID_EXCESS = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/tank_void_excess"); + public static final UITexture OVERLAY_BUTTON_TANK_VOID_ALL = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/tank_void_all"); public static final UITexture OVERLAY_BUTTON_NEI = UITexture.fullImage(GregTech.ID, "gui/overlay_button/nei"); /** diff --git a/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java b/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java new file mode 100644 index 0000000000..cf740a6bc6 --- /dev/null +++ b/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java @@ -0,0 +1,304 @@ +package gregtech.api.interfaces.modularui; + +import static gregtech.api.metatileentity.BaseTileEntity.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; + +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.VoidingMode; +import gregtech.api.gui.modularui.GT_UITextures; + +/** + * Machines implementing this interface can have logic and GUI buttons + * to configure various behaviors regarding multiblock. + * + */ +public interface ControllerWithOptionalFeatures { + + boolean isAllowedToWork(); + + void disableWorking(); + + void enableWorking(); + + Pos2d getPowerSwitchButtonPos(); + + default ButtonWidget createPowerSwitchButton(IWidgetBuilder builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isAllowedToWork()) { + disableWorking(); + } else { + enableWorking(); + } + }) + .setPlayClickSoundResource( + () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation + : SoundResource.GUI_BUTTON_DOWN.resourceLocation) + .setBackground(() -> { + if (isAllowedToWork()) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }; + } else { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF }; + } + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> { + if (val) enableWorking(); + else disableWorking(); + }), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getPowerSwitchButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + /** + * @return if this machine can prevent excess item and fluid from voiding. + */ + boolean supportsVoidProtection(); + + /** + * @return if this machine is configured to not void excess item. + */ + default boolean protectsExcessItem() { + return supportsVoidProtection() && getVoidingMode().protectItem; + } + + /** + * @return if this machine is configured to not void excess fluid. + */ + default boolean protectsExcessFluid() { + return supportsVoidProtection() && getVoidingMode().protectFluid; + } + + VoidingMode getVoidingMode(); + + void setVoidingMode(VoidingMode mode); + + Pos2d getVoidingModeButtonPos(); + + default ButtonWidget createVoidExcessButton(IWidgetBuilder builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsVoidProtection()) { + switch (clickData.mouseButton) { + case 0 -> setVoidingMode(getVoidingMode().next()); + case 1 -> setVoidingMode(getVoidingMode().previous()); + } + widget.notifyTooltipChange(); + } + }) + .setPlayClickSound(supportsVoidProtection()) + .setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(getVoidingMode().buttonTexture); + ret.add(getVoidingMode().buttonOverlay); + if (!supportsVoidProtection()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer( + () -> getVoidingMode().ordinal(), + val -> setVoidingMode(VoidingMode.fromOrdinal(val))), + builder) + .dynamicTooltip( + () -> Arrays.asList( + StatCollector.translateToLocal("GT5U.gui.button.voiding_mode"), + StatCollector.translateToLocal(getVoidingMode().getTransKey()))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getVoidingModeButtonPos()) + .setSize(16, 16); + if (!supportsVoidProtection()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return (ButtonWidget) button; + } + + /** + * @return if the multi supports input separation. + */ + boolean supportsInputSeparation(); + + /** + * @return true if input separation is enabled, else false. This is getter is used for displaying the icon in the + * GUI + */ + boolean isInputSeparationEnabled(); + + void setInputSeparation(boolean enabled); + + Pos2d getInputSeparationButtonPos(); + + default ButtonWidget createInputSeparationButton(IWidgetBuilder builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsInputSeparation()) { + setInputSeparation(!isInputSeparationEnabled()); + } + }) + .setPlayClickSound(supportsInputSeparation()) + .setBackground(() -> { + List ret = new ArrayList<>(); + if (isInputSeparationEnabled()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); + } + } + if (!supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(this::isInputSeparationEnabled, this::setInputSeparation), + builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getInputSeparationButtonPos()) + .setSize(16, 16); + if (!supportsInputSeparation()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return (ButtonWidget) button; + } + + /** + * @return if the multi supports batch mode. + */ + boolean supportsBatchMode(); + + /** + * @return true if batch mode is enabled, else false. This is getter is used for displaying the icon in the GUI + */ + boolean isBatchModeEnabled(); + + void setBatchMode(boolean enabled); + + Pos2d getBatchModeButtonPos(); + + default ButtonWidget createBatchModeButton(IWidgetBuilder builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsBatchMode()) { + setBatchMode(!isBatchModeEnabled()); + } + }) + .setPlayClickSound(supportsBatchMode()) + .setBackground(() -> { + List ret = new ArrayList<>(); + if (isBatchModeEnabled()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); + } + } + if (!supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(this::isBatchModeEnabled, this::setBatchMode), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getBatchModeButtonPos()) + .setSize(16, 16); + if (!supportsBatchMode()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return (ButtonWidget) button; + } + + /** + * Override this if you are a multi-block that has added support for single recipe locking. + */ + boolean supportsSingleRecipeLocking(); + + /** + * @return true if recipe locking is enabled, else false. This is getter is used for displaying the icon in the GUI + */ + boolean isRecipeLockingEnabled(); + + void setRecipeLocking(boolean enabled); + + Pos2d getRecipeLockingButtonPos(); + + default ButtonWidget createLockToSingleRecipeButton(IWidgetBuilder builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsSingleRecipeLocking()) { + setRecipeLocking(!isRecipeLockingEnabled()); + } + }) + .setPlayClickSound(supportsSingleRecipeLocking()) + .setBackground(() -> { + List ret = new ArrayList<>(); + if (isRecipeLockingEnabled()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); + } + } + if (!supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(this::isRecipeLockingEnabled, this::setRecipeLocking), + builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getRecipeLockingButtonPos()) + .setSize(16, 16); + if (!supportsSingleRecipeLocking()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return (ButtonWidget) button; + } +} diff --git a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java index d38a3d98fd..4c49a88819 100644 --- a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java +++ b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java @@ -23,7 +23,8 @@ public class ComplexParallelProcessingLogic { protected final long[] availableEut; protected final long[] eut; protected final long[] durations; - protected boolean[] isVoidProtected; + protected boolean[] isItemVoidProtected; + protected boolean[] isFluidVoidProtected; public ComplexParallelProcessingLogic(int maxComplexParallels) { this(null, maxComplexParallels); @@ -39,7 +40,8 @@ public class ComplexParallelProcessingLogic { eut = new long[maxComplexParallels]; availableEut = new long[maxComplexParallels]; durations = new long[maxComplexParallels]; - isVoidProtected = new boolean[maxComplexParallels]; + isItemVoidProtected = new boolean[maxComplexParallels]; + isFluidVoidProtected = new boolean[maxComplexParallels]; } public ComplexParallelProcessingLogic setRecipeMap(GT_Recipe.GT_Recipe_Map recipeMap) { @@ -73,9 +75,10 @@ public class ComplexParallelProcessingLogic { return this; } - public ComplexParallelProcessingLogic setVoidProtection(int index, boolean shouldVoidProtect) { + public ComplexParallelProcessingLogic setVoidProtection(int index, boolean protectItem, boolean protectFluid) { if (index >= 0 && index < maxComplexParallels) { - isVoidProtected[index] = shouldVoidProtect; + isItemVoidProtected[index] = protectItem; + isFluidVoidProtected[index] = protectFluid; } return this; } @@ -122,13 +125,10 @@ public class ComplexParallelProcessingLogic { .setItemInputs(inputItems[index]) .setFluidInputs(inputFluids[index]) .setAvailableEUt(availableEut[index]) + .setController(tileEntity, isItemVoidProtected[index], isFluidVoidProtected[index]) .enableConsumption() .enableOutputCalculation(); - if (isVoidProtected[index]) { - helper.enableVoidProtection(tileEntity); - } - helper.build(); if (helper.getCurrentParallel() <= 0) { diff --git a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java index 463219fa3c..0d3f6cf7a5 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java @@ -672,6 +672,7 @@ public abstract class BaseTileEntity extends TileEntity implements IHasWorldObje STALLED_VENT_TOOLTIP = "GT5U.machines.stalled_vent.tooltip", FLUID_TRANSFER_TOOLTIP = "GT5U.machines.fluid_transfer.tooltip", ITEM_TRANSFER_TOOLTIP = "GT5U.machines.item_transfer.tooltip", POWER_SOURCE_KEY = "GT5U.machines.powersource.", + BUTTON_FORBIDDEN_TOOLTIP = "GT5U.gui.button.forbidden", NEI_TRANSFER_STEAM_TOOLTIP = "GT5U.machines.nei_transfer.steam.tooltip", NEI_TRANSFER_VOLTAGE_TOOLTIP = "GT5U.machines.nei_transfer.voltage.tooltip"; diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java index af0219c4b1..a60f9b1cd2 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java @@ -1,7 +1,6 @@ package gregtech.api.metatileentity.implementations; import static gregtech.api.enums.GT_Values.*; -import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; import static mcp.mobius.waila.api.SpecialChars.GREEN; import static mcp.mobius.waila.api.SpecialChars.RED; import static mcp.mobius.waila.api.SpecialChars.RESET; @@ -9,6 +8,7 @@ import static mcp.mobius.waila.api.SpecialChars.RESET; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.client.Minecraft; @@ -29,12 +29,9 @@ import org.jetbrains.annotations.TestOnly; import org.lwjgl.input.Keyboard; import com.google.common.collect.Iterables; -import com.gtnewhorizons.modularui.api.drawable.IDrawable; -import com.gtnewhorizons.modularui.api.drawable.UITexture; import com.gtnewhorizons.modularui.api.math.Pos2d; import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.api.widget.Widget; import com.gtnewhorizons.modularui.common.widget.*; import cpw.mods.fml.relauncher.Side; @@ -43,9 +40,11 @@ import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.ConfigCategories; import gregtech.api.enums.SoundResource; +import gregtech.api.enums.VoidingMode; import gregtech.api.gui.modularui.GT_UIInfos; import gregtech.api.gui.modularui.GT_UITextures; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.modularui.ControllerWithOptionalFeatures; import gregtech.api.interfaces.modularui.IAddGregtechLogo; import gregtech.api.interfaces.modularui.IAddUIWidgets; import gregtech.api.interfaces.modularui.IBindPlayerInventoryUI; @@ -64,7 +63,7 @@ import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity - implements IAddGregtechLogo, IAddUIWidgets, IBindPlayerInventoryUI { + implements ControllerWithOptionalFeatures, IAddGregtechLogo, IAddUIWidgets, IBindPlayerInventoryUI { public static boolean disableMaintenance; public boolean mMachine = false, mWrench = false, mScrewdriver = false, mSoftHammer = false, mHardHammer = false, @@ -82,10 +81,11 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity public boolean mLockedToSingleRecipe = false; protected boolean inputSeparation = false; - protected boolean voidExcess = true; + protected VoidingMode voidingMode = VoidingMode.VOID_ALL; protected boolean batchMode = false; protected static String INPUT_SEPARATION_NBT_KEY = "inputSeparation"; protected static String VOID_EXCESS_NBT_KEY = "voidExcess"; + protected static String VOIDING_MODE_NBT_KEY = "voidingMode"; protected static String BATCH_MODE_NBT_KEY = "batchMode"; public GT_Single_Recipe_Check mSingleRecipeCheck = null; @@ -123,7 +123,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity .get(ConfigCategories.machineconfig, "MultiBlockMachines.damageFactorLow", 5); this.damageFactorHigh = (float) GregTech_API.sMachineFile .get(ConfigCategories.machineconfig, "MultiBlockMachines.damageFactorHigh", 0.6f); - voidExcess = !isVoidExcessButtonEnabled(); + voidingMode = supportsVoidProtection() ? VoidingMode.VOID_NONE : VoidingMode.VOID_ALL; } public static boolean isValidMetaTileEntity(MetaTileEntity aMetaTileEntity) { @@ -143,11 +143,6 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity return side != getBaseMetaTileEntity().getFrontFacing(); } - /** Override this if you are a multi-block that has added support for single recipe locking. */ - public boolean supportsSingleRecipeLocking() { - return false; - } - @Override public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (supportsSingleRecipeLocking()) { @@ -235,7 +230,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity aNBT.setBoolean("mCrowbar", mCrowbar); aNBT.setBoolean(BATCH_MODE_NBT_KEY, batchMode); aNBT.setBoolean(INPUT_SEPARATION_NBT_KEY, inputSeparation); - aNBT.setBoolean(VOID_EXCESS_NBT_KEY, voidExcess); + aNBT.setString(VOIDING_MODE_NBT_KEY, voidingMode.name); } @Override @@ -260,7 +255,12 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity } batchMode = aNBT.getBoolean(BATCH_MODE_NBT_KEY); inputSeparation = aNBT.getBoolean(INPUT_SEPARATION_NBT_KEY); - voidExcess = aNBT.getBoolean(VOID_EXCESS_NBT_KEY); + if (aNBT.hasKey(VOIDING_MODE_NBT_KEY, Constants.NBT.TAG_STRING)) { + voidingMode = VoidingMode.fromName(aNBT.getString(VOIDING_MODE_NBT_KEY)); + } else if (aNBT.hasKey(VOID_EXCESS_NBT_KEY)) { + // backward compatibility + voidingMode = aNBT.getBoolean(VOID_EXCESS_NBT_KEY) ? VoidingMode.VOID_ALL : VoidingMode.VOID_NONE; + } int aOutputItemsLength = aNBT.getInteger("mOutputItemsLength"); if (aOutputItemsLength > 0) { @@ -1520,103 +1520,168 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity } /** - * Checks if items can fit in the output buses. If your outputs come from GT_Recipe, - * {@link GT_ParallelHelper} will work better. + * Checks if all the item / fluid outputs of the recipe can be outputted to the buses / hatches. + * If void protection is enabled, it also checks for {@link #protectsExcessItem()} and + * {@link #protectsExcessFluid()}, so you don't need to call them along with this method. + *

+ * If you're using {@link GT_ParallelHelper}, it will handle void protection and return 0 parallel + * if all the output cannot be dumped into buses / hatches. In that case you won't use this method. */ - protected boolean canFitOutput(ItemStack[] items) { - return canFitOutput(items, null); + protected boolean canOutputAll(@Nonnull GT_Recipe recipe) { + return canOutputAll(recipe.mOutputs, recipe.mFluidOutputs); } /** - * Checks if fluids can fit in the output hatches. If your outputs come from GT_Recipe, - * {@link GT_ParallelHelper} will work better. + * Checks if all the items can be outputted to the output buses. + * If void protection is enabled, it also checks for {@link #protectsExcessItem()}, + * so you don't need to call it along with this method. */ - protected boolean canFitOutput(FluidStack[] fluids) { - return canFitOutput(null, fluids); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + protected boolean canOutputAll(ItemStack[] items) { + return canOutputAll(items, null); } /** - * Checks if items / fluids can fit in the output buses / hatches. If your outputs come from GT_Recipe, - * {@link GT_ParallelHelper} will work better. + * Checks if all the fluids can be outputted to the output hatches. + * If void protection is enabled, it also checks for {@link #protectsExcessFluid()}, + * so you don't need to call it along with this method. */ - protected boolean canFitOutput(@Nullable ItemStack[] items, @Nullable FluidStack[] fluids) { - VoidProtectionHelper voidProtectionHelper = new VoidProtectionHelper().setController(this); - if (items != null) { - voidProtectionHelper.setItemOutputs(items); - } - if (fluids != null) { - voidProtectionHelper.setFluidOutputs(fluids); + protected boolean canOutputAll(FluidStack[] fluids) { + return canOutputAll(null, fluids); + } + + /** + * Checks if all the items / fluids can be outputted to output buses / hatches. + * If void protection is enabled, it also checks for {@link #protectsExcessItem()} and + * {@link #protectsExcessFluid()}, so you don't need to call them along with this method. + */ + protected boolean canOutputAll(@Nullable ItemStack[] items, @Nullable FluidStack[] fluids) { + if (!protectsExcessItem() && !protectsExcessFluid()) { + return true; } - voidProtectionHelper.build(); + + VoidProtectionHelper voidProtectionHelper = new VoidProtectionHelper().setController(this) + .setItemOutputs(items) + .setFluidOutputs(fluids) + .build(); return voidProtectionHelper.getMaxParallel() > 0; } @Override - public boolean useModularUI() { - return true; + public boolean isAllowedToWork() { + return getBaseMetaTileEntity().isAllowedToWork(); } @Override - public int getGUIWidth() { - return 198; + public void disableWorking() { + getBaseMetaTileEntity().disableWorking(); } @Override - public int getGUIHeight() { - return 192; + public void enableWorking() { + getBaseMetaTileEntity().enableWorking(); } - /** - * @return if the multi supports input separation. If you want to use it you need to use {@link #inputSeparation}. - */ - protected boolean isInputSeparationButtonEnabled() { - return false; + @Override + public Pos2d getPowerSwitchButtonPos() { + return new Pos2d(174, 148); } - /** - * @return if the multi supports batch mode. If you want to use it you need to use {@link #batchMode}. - */ - protected boolean isBatchModeButtonEnabled() { + @Override + public boolean supportsVoidProtection() { return false; } - /** - * @return if the multi supports void excess to be toggled. If you want to use it you need to use - * {@link #voidExcess}. - */ - protected boolean isVoidExcessButtonEnabled() { + @Override + public VoidingMode getVoidingMode() { + return voidingMode; + } + + @Override + public void setVoidingMode(VoidingMode mode) { + this.voidingMode = mode; + } + + @Override + public Pos2d getVoidingModeButtonPos() { + return new Pos2d(8, 91); + } + + @Override + public boolean supportsInputSeparation() { return false; } - /** - * @return true if input separation is enabled, else false. This is getter is used for displaying the icon in the - * GUI - */ - protected boolean isInputSeparationEnabled() { + @Override + public boolean isInputSeparationEnabled() { return inputSeparation; } - /** - * @return true if batch mode is enabled, else false. This is getter is used for displaying the icon in the GUI - */ - protected boolean isBatchModeEnabled() { + @Override + public void setInputSeparation(boolean enabled) { + this.inputSeparation = enabled; + } + + @Override + public Pos2d getInputSeparationButtonPos() { + return new Pos2d(26, 91); + } + + @Override + public boolean supportsBatchMode() { + return false; + } + + @Override + public boolean isBatchModeEnabled() { return batchMode; } - /** - * @return true if void excess is enabled, else false. This is getter is used for displaying the icon in the GUI - */ - protected boolean isVoidExcessEnabled() { - return voidExcess; + @Override + public void setBatchMode(boolean enabled) { + this.batchMode = enabled; } - /** - * @return true if recipe locking is enabled, else false. This is getter is used for displaying the icon in the GUI - */ - protected boolean isRecipeLockingEnabled() { + @Override + public Pos2d getBatchModeButtonPos() { + return new Pos2d(44, 91); + } + + @Override + public boolean supportsSingleRecipeLocking() { + return false; + } + + @Override + public boolean isRecipeLockingEnabled() { return mLockedToSingleRecipe; } + @Override + public void setRecipeLocking(boolean enabled) { + this.mLockedToSingleRecipe = enabled; + } + + @Override + public Pos2d getRecipeLockingButtonPos() { + return new Pos2d(62, 91); + } + + @Override + public boolean useModularUI() { + return true; + } + + @Override + public int getGUIWidth() { + return 198; + } + + @Override + public int getGUIHeight() { + return 192; + } + @Override public void bindPlayerInventoryUI(ModularWindow.Builder builder, UIBuildContext buildContext) { builder.bindPlayerInventory(buildContext.getPlayer(), new Pos2d(7, 109), getGUITextureSet().getItemSlot()); @@ -1637,23 +1702,11 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity drawTexts(screenElements, inventorySlot); builder.widget(screenElements); - builder.widget(createPowerSwitchButton()) - .widget(new FakeSyncWidget.BooleanSyncer(() -> getBaseMetaTileEntity().isAllowedToWork(), val -> { - if (val) getBaseMetaTileEntity().enableWorking(); - else getBaseMetaTileEntity().disableWorking(); - })); - - builder.widget(createVoidExcessButton()) - .widget(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val)); - - builder.widget(createInputSeparationButton()) - .widget(new FakeSyncWidget.BooleanSyncer(() -> inputSeparation, val -> inputSeparation = val)); - - builder.widget(createBatchModeButton()) - .widget(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val)); - - builder.widget(createLockToSingleRecipeButton()) - .widget(new FakeSyncWidget.BooleanSyncer(() -> mLockedToSingleRecipe, val -> mLockedToSingleRecipe = val)); + builder.widget(createPowerSwitchButton(builder)) + .widget(createVoidExcessButton(builder)) + .widget(createInputSeparationButton(builder)) + .widget(createBatchModeButton(builder)) + .widget(createLockToSingleRecipeButton(builder)); } @Override @@ -1759,162 +1812,6 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity })); } - protected ButtonWidget createPowerSwitchButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (getBaseMetaTileEntity().isAllowedToWork()) { - getBaseMetaTileEntity().disableWorking(); - } else { - getBaseMetaTileEntity().enableWorking(); - } - }) - .setPlayClickSoundResource( - () -> getBaseMetaTileEntity().isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation - : SoundResource.GUI_BUTTON_DOWN.resourceLocation) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (getBaseMetaTileEntity().isAllowedToWork()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF); - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(174, 148) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected ButtonWidget createVoidExcessButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isVoidExcessButtonEnabled()) { - voidExcess = !voidExcess; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isVoidExcessButtonEnabled()) { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF); - } - } else { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(8, 91) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected ButtonWidget createInputSeparationButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isInputSeparationButtonEnabled()) { - inputSeparation = !inputSeparation; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isInputSeparationButtonEnabled()) { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); - } - } else { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(26, 91) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected ButtonWidget createBatchModeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isBatchModeButtonEnabled()) { - batchMode = !batchMode; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isBatchModeButtonEnabled()) { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); - } - } else { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(44, 91) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected ButtonWidget createLockToSingleRecipeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (supportsSingleRecipeLocking()) { - mLockedToSingleRecipe = !mLockedToSingleRecipe; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (supportsSingleRecipeLocking()) { - if (isRecipeLockingEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); - } - } else { - if (isRecipeLockingEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(62, 91) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - @TestOnly protected void setEnergyHatches(ArrayList EnergyHatches) { this.mEnergyHatches = EnergyHatches; diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java index 3839c949db..808c16a200 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java @@ -1,7 +1,5 @@ package gregtech.api.multitileentity.multiblock.base; -import static mcp.mobius.waila.api.SpecialChars.*; - import java.util.ArrayList; import java.util.List; import java.util.stream.LongStream; @@ -123,7 +121,7 @@ public abstract class ComplexParallelController> extends MultiTileBasicMachine implements IAlignment, - IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { +public abstract class Controller> extends MultiTileBasicMachine + implements IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, + ISurvivalConstructable, ControllerWithOptionalFeatures { public static final String ALL_INVENTORIES_NAME = "all"; @@ -132,7 +131,7 @@ public abstract class Controller> extends MultiTileBasic private String inventoryName; private String tankName; protected boolean separateInputs = false; - protected boolean voidExcess = false; + protected VoidingMode voidingMode = supportsVoidProtection() ? VoidingMode.VOID_NONE : VoidingMode.VOID_ALL; protected boolean batchMode = false; protected boolean recipeLock = false; /** If this is set to true, the machine will get default WAILA behavior */ @@ -207,7 +206,7 @@ public abstract class Controller> extends MultiTileBasic saveUpgradeInventoriesToNBT(nbt); saveUpgradeTanksToNBT(nbt); - nbt.setBoolean(NBT.VOID_EXCESS, voidExcess); + nbt.setString(NBT.VOIDING_MODE, voidingMode.name); nbt.setBoolean(NBT.SEPARATE_INPUTS, separateInputs); nbt.setBoolean(NBT.RECIPE_LOCK, recipeLock); nbt.setBoolean(NBT.BATCH_MODE, batchMode); @@ -296,7 +295,7 @@ public abstract class Controller> extends MultiTileBasic loadUpgradeInventoriesFromNBT(nbt); loadUpgradeTanksFromNBT(nbt); - voidExcess = nbt.getBoolean(NBT.VOID_EXCESS); + voidingMode = VoidingMode.fromName(nbt.getString(NBT.VOIDING_MODE)); separateInputs = nbt.getBoolean(NBT.SEPARATE_INPUTS); recipeLock = nbt.getBoolean(NBT.RECIPE_LOCK); batchMode = nbt.getBoolean(NBT.BATCH_MODE); @@ -1781,7 +1780,7 @@ public abstract class Controller> extends MultiTileBasic .withOffset(2, 4)) .addTooltip(getLocalName()) .setPos(20 * (page - 1), -20)) - .addPage(createMainPage().setSize(getGUIWidth(), getGUIHeight())); + .addPage(createMainPage(builder).setSize(getGUIWidth(), getGUIHeight())); if (hasItemInput()) { tabs.addTabButton( new TabButton(page++) @@ -1864,33 +1863,25 @@ public abstract class Controller> extends MultiTileBasic builder.widget(tabs); } - protected MultiChildWidget createMainPage() { + protected MultiChildWidget createMainPage(IWidgetBuilder builder) { MultiChildWidget page = new MultiChildWidget(); page.addChild( new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) .setPos(7, 4) .setSize(160, 75)) - .addChild(createButtons()); + .addChild(createButtons(builder)); return page; } - protected MultiChildWidget createButtons() { + protected MultiChildWidget createButtons(IWidgetBuilder builder) { MultiChildWidget buttons = new MultiChildWidget(); buttons.setSize(16, 167) .setPos(7, 86); - buttons.addChild(createPowerSwitchButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> { - if (val) enableWorking(); - else disableWorking(); - })) - .addChild(createVoidExcessButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val)) - .addChild(createInputSeparationButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> separateInputs, val -> separateInputs = val)) - .addChild(createBatchModeButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val)) - .addChild(createLockToSingleRecipeButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> recipeLock, val -> recipeLock = val)); + buttons.addChild(createPowerSwitchButton(builder)) + .addChild(createVoidExcessButton(builder)) + .addChild(createInputSeparationButton(builder)) + .addChild(createBatchModeButton(builder)) + .addChild(createLockToSingleRecipeButton(builder)); return buttons; } @@ -1966,194 +1957,91 @@ public abstract class Controller> extends MultiTileBasic .setPos(52, 7); } - protected ButtonWidget createPowerSwitchButton() { - ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isAllowedToWork()) { - disableWorking(); - } else { - enableWorking(); - } - }) - .setPlayClickSoundResource( - () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation - : SoundResource.GUI_BUTTON_DOWN.resourceLocation); - button.setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isAllowedToWork()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF); - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(144, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return button; - } - - protected ButtonWidget createVoidExcessButton() { - ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isVoidExcessButtonEnabled()) { - voidExcess = !voidExcess; - } - }) - .setPlayClickSound(true); - button.setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isVoidExcessButtonEnabled()) { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF); - } - } else { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(54, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return button; + @Override + public Pos2d getPowerSwitchButtonPos() { + return new Pos2d(144, 0); } - protected boolean isVoidExcessEnabled() { - return voidExcess; + @Override + public boolean supportsVoidProtection() { + return true; } - protected boolean isVoidExcessButtonEnabled() { - return true; + @Override + public VoidingMode getVoidingMode() { + return voidingMode; } - protected ButtonWidget createInputSeparationButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isInputSeparationButtonEnabled()) { - separateInputs = !separateInputs; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isInputSeparationButtonEnabled()) { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); - } - } else { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(36, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; + @Override + public void setVoidingMode(VoidingMode mode) { + this.voidingMode = mode; } - protected boolean isInputSeparationEnabled() { - return separateInputs; + @Override + public Pos2d getVoidingModeButtonPos() { + return new Pos2d(54, 0); } - protected boolean isInputSeparationButtonEnabled() { + @Override + public boolean supportsInputSeparation() { return true; } - protected ButtonWidget createBatchModeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isBatchModeButtonEnabled()) { - batchMode = !batchMode; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isBatchModeButtonEnabled()) { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); - } - } else { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(18, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; + @Override + public boolean isInputSeparationEnabled() { + return separateInputs; + } + + @Override + public void setInputSeparation(boolean enabled) { + this.separateInputs = enabled; + } + + @Override + public Pos2d getInputSeparationButtonPos() { + return new Pos2d(36, 0); } - protected boolean