diff options
| author | miozune <miozune@gmail.com> | 2023-05-28 18:21:42 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-28 11:21:42 +0200 |
| commit | 9af741164c5b59c4d884aba48ebeab7db5442d63 (patch) | |
| tree | 5bbbbb5feb67db85aefd5f21fd885a1a0ab71c78 /src/main/java/gregtech/api | |
| parent | 24ad01683a084bebd26152b803ee19bffe78213c (diff) | |
| download | GT5-Unofficial-9af741164c5b59c4d884aba48ebeab7db5442d63.tar.gz GT5-Unofficial-9af741164c5b59c4d884aba48ebeab7db5442d63.tar.bz2 GT5-Unofficial-9af741164c5b59c4d884aba48ebeab7db5442d63.zip | |
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
Diffstat (limited to 'src/main/java/gregtech/api')
11 files changed, 707 insertions, 476 deletions
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. + * <ul> + * <li>Power switch</li> + * <li>Void protection</li> + * <li>Separated input buses</li> + * <li>Batch mode</li> + * <li>Recipe locking</li> + * </ul> + */ +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<UITexture> 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<UITexture> 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<UITexture> 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<UITexture> 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,104 +1520,169 @@ 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. + * <p> + * 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<UITexture> 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<UITexture> 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<UITexture> 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<UITexture> 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<UITexture> 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<GT_MetaTileEntity_Hatch_Energy> 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<T extends ComplexParallelControl boolean result = processingLogic.setInputItems(index, getInputItems(index)) .setInputFluids(index, getInputFluids(index)) .setTileEntity(this) - .setVoidProtection(index, isVoidProtectionEnabled(index)) + .setVoidProtection(index, isVoidProtectionEnabledForItem(index), isVoidProtectionEnabledForFluid(index)) .setEut(index, getEutForComplexParallel(index)) .setPerfectOverclock(hasPerfectOverclock()) .process(index); @@ -181,8 +179,12 @@ public abstract class ComplexParallelController<T extends ComplexParallelControl return getInputFluids(); } - protected boolean isVoidProtectionEnabled(int index) { - return !voidExcess; + protected boolean isVoidProtectionEnabledForItem(int index) { + return protectsExcessItem(); + } + + protected boolean isVoidProtectionEnabledForFluid(int index) { + return protectsExcessFluid(); } protected boolean hasPerfectOverclock() { diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java index 5bec3f1752..afc456f41a 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java @@ -25,7 +25,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; -import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; @@ -52,17 +51,15 @@ import com.gtnewhorizon.structurelib.structure.IStructureElementChain; import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.util.Vec3Impl; import com.gtnewhorizons.modularui.api.ModularUITextures; -import com.gtnewhorizons.modularui.api.drawable.IDrawable; import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; -import com.gtnewhorizons.modularui.api.drawable.UITexture; import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; import com.gtnewhorizons.modularui.api.forge.ListItemHandler; +import com.gtnewhorizons.modularui.api.math.Pos2d; import com.gtnewhorizons.modularui.api.screen.*; +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.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; import com.gtnewhorizons.modularui.common.widget.Scrollable; @@ -76,11 +73,12 @@ import gnu.trove.list.array.TIntArrayList; import gregtech.api.enums.GT_Values; import gregtech.api.enums.GT_Values.NBT; import gregtech.api.enums.OrePrefixes; -import gregtech.api.enums.SoundResource; import gregtech.api.enums.TextureSet; +import gregtech.api.enums.VoidingMode; import gregtech.api.fluid.FluidTankGT; import gregtech.api.gui.modularui.GT_UITextures; import gregtech.api.interfaces.IDescribable; +import gregtech.api.interfaces.modularui.ControllerWithOptionalFeatures; import gregtech.api.logic.PowerLogic; import gregtech.api.logic.ProcessingLogic; import gregtech.api.logic.interfaces.PowerLogicHost; @@ -105,8 +103,9 @@ import mcp.mobius.waila.api.IWailaDataAccessor; /** * Multi Tile Entities - or MuTEs - don't have dedicated hatches, but their casings can become hatches. */ -public abstract class Controller<T extends Controller<T>> extends MultiTileBasicMachine implements IAlignment, - IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { +public abstract class Controller<T extends Controller<T>> 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<T extends Controller<T>> 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<T extends Controller<T>> 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<T extends Controller<T>> 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<T extends Controller<T>> 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<T extends Controller<T>> 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,195 +1957,92 @@ public abstract class Controller<T extends Controller<T>> 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<UITexture> 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<UITexture> 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<UITexture> 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<UITexture> 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 isBatchModeButtonEnabled() { + @Override + public boolean supportsBatchMode() { return true; } - protected boolean isBatchModeEnabled() { + @Override + public boolean isBatchModeEnabled() { return batchMode; } - protected ButtonWidget createLockToSingleRecipeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (supportsSingleRecipeLocking()) { - recipeLock = !recipeLock; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List<UITexture> 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(0, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; + @Override + public void setBatchMode(boolean mode) { + this.batchMode = mode; } - protected boolean supportsSingleRecipeLocking() { + @Override + public Pos2d getBatchModeButtonPos() { + return new Pos2d(18, 0); + } + + @Override + public boolean supportsSingleRecipeLocking() { return false; } - protected boolean isRecipeLockingEnabled() { + @Override + public boolean isRecipeLockingEnabled() { return recipeLock; } @Override + public void setRecipeLocking(boolean enabled) { + this.recipeLock = enabled; + } + + @Override + public Pos2d getRecipeLockingButtonPos() { + return new Pos2d(0, 0); + } + + @Override public ModularWindow createWindowGUI(UIBuildContext buildContext) { return createWindow(buildContext); } diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index 04218f4566..ff45f8213b 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -7,6 +7,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockB import gregtech.api.multitileentity.multiblock.base.Controller; import gregtech.api.objects.XSTR; +@SuppressWarnings({ "unused", "UnusedReturnValue" }) public class GT_ParallelHelper { /** @@ -55,9 +56,13 @@ public class GT_ParallelHelper { */ private FluidStack[] mFluidOutputs; /** - * Does the multi have void protection enabled + * Does the multi have void protection enabled for items */ - private boolean mVoidProtection; + private boolean protectExcessItem; + /** + * Does the multi have void protection enabled for fluids + */ + private boolean protectExcessFluid; /** * Should the Parallel Helper automatically consume for the multi */ @@ -87,20 +92,38 @@ public class GT_ParallelHelper { public GT_ParallelHelper() {} /** - * Enables void protection on a metatile multiblock. + * Sets MetaTE controller, with current configuration for void protection mode. + */ + public GT_ParallelHelper setController(GT_MetaTileEntity_MultiBlockBase machineMeta) { + return setController(machineMeta, machineMeta.protectsExcessItem(), machineMeta.protectsExcessFluid()); + } + + /** + * Sets MetaTE controller, with void protection mode forcibly. */ - public GT_ParallelHelper enableVoidProtection(GT_MetaTileEntity_MultiBlockBase aMachineMeta) { - mVoidProtection = true; - mMachineMeta = aMachineMeta; + public GT_ParallelHelper setController(GT_MetaTileEntity_MultiBlockBase machineMeta, boolean protectExcessItem, + boolean protectExcessFluid) { + this.protectExcessItem = protectExcessItem; + this.protectExcessFluid = protectExcessFluid; + this.mMachineMeta = machineMeta; return this; } /** - * Enables void protection on a multitile multiblock. + * Sets MuTE controller, with current configuration for void protection mode. + */ + public GT_ParallelHelper setController(Controller<?> machineMulti) { + return setController(machineMulti, machineMulti.protectsExcessItem(), machineMulti.protectsExcessFluid()); + } + + /** + * Sets MuTE controller, with void protection mode forcibly. */ - public GT_ParallelHelper enableVoidProtection(Controller<?> aMachineMulti) { - mVoidProtection = true; - mMachineMulti = aMachineMulti; + public GT_ParallelHelper setController(Controller<?> machineMulti, boolean protectExcessItem, + boolean protectExcessFluid) { + this.protectExcessItem = protectExcessItem; + this.protectExcessFluid = protectExcessFluid; + this.mMachineMulti = machineMulti; return this; } @@ -273,12 +296,12 @@ public class GT_ParallelHelper { mMaxParallel *= mBatchModifier; } // Let's look at how many parallels we can get with void protection - if (mVoidProtection) { + if (protectExcessItem || protectExcessFluid) { VoidProtectionHelper voidProtectionHelper = new VoidProtectionHelper(); if (mMachineMeta != null) { - voidProtectionHelper.setController(mMachineMeta); + voidProtectionHelper.setController(mMachineMeta, protectExcessItem, protectExcessFluid); } else if (mMachineMulti != null) { - voidProtectionHelper.setController(mMachineMulti); + voidProtectionHelper.setController(mMachineMulti, protectExcessItem, protectExcessFluid); } voidProtectionHelper.setItemOutputs(mRecipe.mOutputs) .setFluidOutputs(mRecipe.mFluidOutputs) diff --git a/src/main/java/gregtech/api/util/VoidProtectionHelper.java b/src/main/java/gregtech/api/util/VoidProtectionHelper.java index 8b09cd5a3d..9a66a55874 100644 --- a/src/main/java/gregtech/api/util/VoidProtectionHelper.java +++ b/src/main/java/gregtech/api/util/VoidProtectionHelper.java @@ -38,6 +38,14 @@ public class VoidProtectionHelper { */ private Controller<?> machineMulti; /** + * Does void protection enabled for items + */ + private boolean protectExcessItem; + /** + * Does void protection enabled for fluids + */ + private boolean protectExcessFluid; + /** * The maximum possible parallel possible for the multiblock */ private int maxParallel = 1; @@ -57,17 +65,37 @@ public class VoidProtectionHelper { public VoidProtectionHelper() {} /** - * Sets MetaTE controller to use for calculation + * Sets MetaTE controller, with current configuration for void protection mode. */ public VoidProtectionHelper setController(GT_MetaTileEntity_MultiBlockBase machineMeta) { + return setController(machineMeta, machineMeta.protectsExcessItem(), machineMeta.protectsExcessFluid()); + } + + /** + * Sets MetaTE controller, with void protection mode forcibly. + */ + public VoidProtectionHelper setController(GT_MetaTileEntity_MultiBlockBase machineMeta, boolean protectExcessItem, + boolean protectExcessFluid) { + this.protectExcessItem = protectExcessItem; + this.protectExcessFluid = protectExcessFluid; this.machineMeta = machineMeta; return this; } /** - * Sets MuTE controller to use for calculation + * Sets MuTE controller, with current configuration for void protection mode. */ public VoidProtectionHelper setController(Controller<?> machineMulti) { + return setController(machineMulti, machineMulti.protectsExcessItem(), machineMulti.protectsExcessFluid()); + } + + /** + * Sets MuTE controller, with void protection mode forcibly. + */ + public VoidProtectionHelper setController(Controller<?> machineMulti, boolean protectExcessItem, + boolean protectExcessFluid) { + this.protectExcessItem = protectExcessItem; + this.protectExcessFluid = protectExcessFluid; this.machineMulti = machineMulti; return this; } @@ -123,6 +151,8 @@ public class VoidProtectionHelper { fluidOutputs = new FluidStack[0]; } + // Don't check ControllerWithOptionalFeatures#protectsExcessItem nor #protectsExcessFluid here, + // to allow more involved setting for void protections (see ComplexParallelProcessingLogic) if (machineMeta != null) { boolean tMEOutputBus = false; boolean tMEOutputHatch = false; @@ -139,16 +169,20 @@ public class VoidProtectionHelper { break; } } - if (!tMEOutputBus) { + + if (protectExcessItem && itemOutputs.length > 0 && !tMEOutputBus) { maxParallel = Math.min(calculateMaxItemParallelsForMetaTEs(), maxParallel); } - - if (!tMEOutputHatch) { + if (protectExcessFluid && fluidOutputs.length > 0 && !tMEOutputHatch) { maxParallel = Math.min(calculateMaxFluidParallelsForMetaTEs(), maxParallel); } } else if (machineMulti != null) { - maxParallel = Math.min(calculateMaxItemParallelsForMuTEs(), maxParallel); - maxParallel = Math.min(calculateMaxFluidParallelsForMuTEs(), maxParallel); + if (protectExcessItem && itemOutputs.length > 0) { + maxParallel = Math.min(calculateMaxItemParallelsForMuTEs(), maxParallel); + } + if (protectExcessFluid && fluidOutputs.length > 0) { + maxParallel = Math.min(calculateMaxFluidParallelsForMuTEs(), maxParallel); + } } } |
