diff options
author | querns <33518699+querns@users.noreply.github.com> | 2023-09-08 15:39:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-08 22:39:21 +0200 |
commit | 7f837715a8377b24853bf0fea02f23c210b47cfc (patch) | |
tree | ab75df3f15857a83ee653750cb5090225a7c089d /src/main | |
parent | e4f17b7b40503fd34d9dae447802453480b9577c (diff) | |
download | GT5-Unofficial-7f837715a8377b24853bf0fea02f23c210b47cfc.tar.gz GT5-Unofficial-7f837715a8377b24853bf0fea02f23c210b47cfc.tar.bz2 GT5-Unofficial-7f837715a8377b24853bf0fea02f23c210b47cfc.zip |
Adds status messages, action buttons to UI of multiblock drills (#2270)
* Adds several UI elements to multiblock drills
* Spotless
* Adds formatNumbers calls in places where it'd been missed
* Eliminate wildcard import
* Add @NotNull annotations to new fields and methods
Diffstat (limited to 'src/main')
15 files changed, 808 insertions, 56 deletions
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 83aeb1d029..19bf3ca3f4 100644 --- a/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java +++ b/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java @@ -281,6 +281,8 @@ public class GT_UITextures { .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_LOCKED = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/lock_small"); 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 @@ -366,6 +368,17 @@ public class GT_UITextures { .fullImage(GregTech.ID, "gui/overlay_button/use_processing_state.png"); public static final UITexture OVERLAY_BUTTON_USE_INVERTED_PROCESSING_STATE = UITexture .fullImage(GregTech.ID, "gui/overlay_button/use_inverted_processing_state.png"); + public static final UITexture OVERLAY_CHUNK_LOADING = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/chunkloading"); + public static final UITexture OVERLAY_CHUNK_LOADING_OFF = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/chunkloading_off"); + public static final UITexture OVERLAY_WORK_AREA = UITexture.fullImage(GregTech.ID, "gui/overlay_button/work_area"); + public static final UITexture OVERLAY_REPLACE_COBBLE_ON = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/replace_cobble_on"); + public static final UITexture OVERLAY_REPLACE_COBBLE_OFF = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/replace_cobble_off"); + public static final UITexture OVERLAY_RETRACT_PIPE = UITexture + .fullImage(GregTech.ID, "gui/overlay_button/retract_pipes"); /** * Can adjust size as needed. diff --git a/src/main/java/gregtech/api/gui/widgets/GT_DisabledWhileActiveButton.java b/src/main/java/gregtech/api/gui/widgets/GT_DisabledWhileActiveButton.java new file mode 100644 index 0000000000..e86589ac2a --- /dev/null +++ b/src/main/java/gregtech/api/gui/widgets/GT_DisabledWhileActiveButton.java @@ -0,0 +1,104 @@ +package gregtech.api.gui.widgets; + +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +import net.minecraft.util.StatCollector; + +import org.jetbrains.annotations.NotNull; + +import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; + +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.interfaces.tileentity.IMachineProgress; + +public class GT_DisabledWhileActiveButton extends ButtonWidget { + + @NotNull + private final WeakReference<IMachineProgress> machineRef; + + public GT_DisabledWhileActiveButton(@NotNull IMachineProgress machine, @NotNull ModularWindow.Builder builder) { + super(); + machineRef = new WeakReference<>(machine); + + super.attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> isMachineActive().orElse(true), a -> {}), + builder, + (widget, aBoolean) -> widget.notifyTooltipChange()); + + super.dynamicTooltip(this::generateTooltip); + } + + @NotNull + @Override + public ButtonWidget setOnClick(@NotNull BiConsumer<ClickData, Widget> clickAction) { + return super.setOnClick((clickData, widget) -> isMachineActive().ifPresent(isActive -> { + if (!isActive) { + clickAction.accept(clickData, widget); + } + })); + } + + @NotNull + @Override + public Widget setBackground(@NotNull IDrawable... drawables) { + return super.setBackground(() -> appendLockedOverlay(drawables)); + } + + @NotNull + @Override + public Widget setBackground(@NotNull Supplier<IDrawable[]> drawablesSupplier) { + return super.setBackground(() -> appendLockedOverlay(drawablesSupplier.get())); + } + + @NotNull + @Override + public Widget dynamicTooltip(@NotNull Supplier<List<String>> dynamicTooltip) { + return super.dynamicTooltip(() -> { + ImmutableList.Builder<String> tooltips = ImmutableList.<String>builder() + .addAll(dynamicTooltip.get()); + tooltips.addAll(generateTooltip()); + + return tooltips.build(); + }); + } + + @NotNull + private Optional<Boolean> isMachineActive() { + return Optional.ofNullable(machineRef.get()) + .map(IMachineProgress::isActive); + } + + @NotNull + private IDrawable[] appendLockedOverlay(@NotNull IDrawable[] drawables) { + return isMachineActive().map(isActive -> { + if (isActive) { + final IDrawable[] copy = Arrays.copyOf(drawables, drawables.length + 1); + copy[drawables.length] = GT_UITextures.OVERLAY_BUTTON_LOCKED; + return copy; + } + return drawables; + }) + .orElse(drawables); + } + + @NotNull + private List<String> generateTooltip() { + return isMachineActive().map(isActive -> { + if (isActive) { + return ImmutableList.of(StatCollector.translateToLocal("GT5U.gui.button.forbidden_while_running")); + } + return ImmutableList.<String>of(); + }) + .orElse(ImmutableList.of()); + } +} diff --git a/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java index aa129bab86..ad0d56708e 100644 --- a/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java +++ b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java @@ -84,6 +84,13 @@ public final class CheckRecipeResultRegistry { * Machine had an internal error */ public static final CheckRecipeResult INTERNAL_ERROR = SimpleCheckRecipeResult.ofFailure("internal_error"); + /** Multiblock ore drill has no drilling fluid */ + public static final CheckRecipeResult NO_DRILLING_FLUID = SimpleCheckRecipeResult.ofFailure("no_drilling_fluid"); + /** Multiblock drill is missing mining pipe */ + public static final CheckRecipeResult MISSING_MINING_PIPE = SimpleCheckRecipeResult.ofFailure("no_mining_pipe"); + /** Concrete backfiller is out of concrete */ + public static final CheckRecipeResult BACKFILLER_NO_CONCRETE = SimpleCheckRecipeResult + .ofFailure("backfiller_no_concrete"); /** * Cannot process recipe because the machine cannot handle required EUt. diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java index 1c7f802a38..3e9238003f 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java @@ -9,13 +9,20 @@ import static gregtech.api.enums.GT_Values.VN; import java.util.List; import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; import gregtech.api.GregTech_API; import gregtech.api.enums.Materials; import gregtech.api.interfaces.IHatchElement; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.api.util.GT_Utility; @@ -23,12 +30,21 @@ public abstract class GT_MetaTileEntity_ConcreteBackfillerBase extends GT_MetaTi private int mLastXOff = 0, mLastZOff = 0; + /** Used to drive the readout in the GUI for the backfiller's current y-level. */ + private int clientYHead; + public GT_MetaTileEntity_ConcreteBackfillerBase(int aID, String aName, String aNameRegional) { super(aID, aName, aNameRegional); + initRecipeResults(); } public GT_MetaTileEntity_ConcreteBackfillerBase(String aName) { super(aName); + initRecipeResults(); + } + + private void initRecipeResults() { + addResultMessage(STATE_UPWARD, true, "backfiller_working"); } protected GT_Multiblock_Tooltip_Builder createTooltip(String aStructureName) { @@ -107,6 +123,7 @@ public abstract class GT_MetaTileEntity_ConcreteBackfillerBase extends GT_MetaTi } else { workState = STATE_DOWNWARD; stopMachine(); + setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.backfiller_finished")); return false; } } @@ -123,7 +140,10 @@ public abstract class GT_MetaTileEntity_ConcreteBackfillerBase extends GT_MetaTi } private boolean tryRefillBlock(int aX, int aY, int aZ) { - if (!tryConsumeFluid()) return false; + if (!tryConsumeFluid()) { + setRuntimeFailureReason(CheckRecipeResultRegistry.BACKFILLER_NO_CONCRETE); + return false; + } getBaseMetaTileEntity().getWorld() .setBlock(aX, aY, aZ, GregTech_API.sBlockConcretes, 8, 3); return true; @@ -136,4 +156,21 @@ public abstract class GT_MetaTileEntity_ConcreteBackfillerBase extends GT_MetaTi } return true; } + + @Override + protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) { + super.drawTexts(screenElements, inventorySlot); + screenElements + .widget( + TextWidget + .dynamicString( + () -> StatCollector.translateToLocalFormatted( + "GT5U.gui.text.backfiller_current_area", + GT_Utility.formatNumbers(clientYHead))) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_UPWARD)) + .widget(new FakeSyncWidget.IntegerSyncer(this::getYHead, newInt -> clientYHead = newInt)) + .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, newInt -> workState = newInt)); + } } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java index 77b5073c86..983e6c5998 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java @@ -16,12 +16,16 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_ACT import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_ACTIVE_GLOW; import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_GLOW; import static gregtech.api.enums.Textures.BlockIcons.getCasingTextureForId; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; import static gregtech.api.util.GT_StructureUtility.buildHatchAdder; import static gregtech.api.util.GT_StructureUtility.ofFrame; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; @@ -29,6 +33,7 @@ import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.StatCollector; import net.minecraft.world.ChunkCoordIntPair; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.ForgeDirection; @@ -41,10 +46,22 @@ import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructa import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.math.Alignment; +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.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; import gregtech.api.GregTech_API; import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.gui.widgets.GT_DisabledWhileActiveButton; import gregtech.api.interfaces.IChunkLoader; import gregtech.api.interfaces.IHatchElement; import gregtech.api.interfaces.ITexture; @@ -56,6 +73,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataA import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy; import gregtech.api.objects.GT_ChunkManager; import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; import gregtech.api.recipe.check.SimpleCheckRecipeResult; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_ModHandler; @@ -127,13 +145,29 @@ public abstract class GT_MetaTileEntity_DrillerBase return zDrill; } + protected int getYHead() { + return yHead; + } + protected int workState; - protected static final int STATE_DOWNWARD = 0, STATE_AT_BOTTOM = 1, STATE_UPWARD = 2; + protected static final int STATE_DOWNWARD = 0, STATE_AT_BOTTOM = 1, STATE_UPWARD = 2, STATE_ABORT = 3; protected boolean mChunkLoadingEnabled = true; protected ChunkCoordIntPair mCurrentChunk = null; protected boolean mWorkChunkNeedsReload = true; + /** Stores default result messages for success/failures of each work state. */ + private final Map<ResultRegistryKey, CheckRecipeResult> resultRegistry = new HashMap<>(); + + /** Allows inheritors to supply custom runtime failure messages. */ + private CheckRecipeResult runtimeFailure = null; + + /** Allows inheritors to supply custom shutdown failure messages. */ + private @NotNull String shutdownReason = ""; + + /** Allows inheritors to suppress wiping the last error if the machine is forcibly turned off. */ + protected boolean suppressErrorWipe = false; + public GT_MetaTileEntity_DrillerBase(int aID, String aName, String aNameRegional) { super(aID, aName, aNameRegional); initFields(); @@ -154,6 +188,16 @@ public abstract class GT_MetaTileEntity_DrillerBase : W; casingTextureIndex = getCasingTextureIndex(); workState = STATE_DOWNWARD; + + // Inheritors can overwrite these to add custom operating messages. + addResultMessage(STATE_DOWNWARD, true, "deploying_pipe"); + addResultMessage(STATE_DOWNWARD, false, "extracting_pipe"); + addResultMessage(STATE_AT_BOTTOM, true, "drilling"); + addResultMessage(STATE_AT_BOTTOM, false, "no_mining_pipe"); + addResultMessage(STATE_UPWARD, true, "retracting_pipe"); + addResultMessage(STATE_UPWARD, false, "drill_generic_finished"); + addResultMessage(STATE_ABORT, true, "retracting_pipe"); + addResultMessage(STATE_ABORT, false, "drill_retract_pipes_finished"); } @Override @@ -380,6 +424,7 @@ public abstract class GT_MetaTileEntity_DrillerBase switch (tryLowerPipeState()) { case 2 -> { mMaxProgresstime = 0; + setRuntimeFailureReason(CheckRecipeResultRegistry.MISSING_MINING_PIPE); return false; } case 3 -> { @@ -417,6 +462,49 @@ public abstract class GT_MetaTileEntity_DrillerBase } } + /** Called once when the abort button is clicked. Use to perform any needed cleanup (e.g. unloading chunks.) */ + protected void onAbort() {} + + protected void abortDrilling() { + if (workState != STATE_ABORT) { + workState = STATE_ABORT; + onAbort(); + setShutdownReason(""); + + if (!isAllowedToWork()) { + enableWorking(); + } + } + } + + // This is a distinct state from workingUpward, because some inheritors (like concrete backfiller) operate + // exclusively on the workingUpward phase. It also allows for more distinct status messages. + protected boolean workingToAbortOperation(@NotNull ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, + int zPipe, int yHead, int oldYHead) { + if (tryPickPipe()) { + return true; + } else { + workState = STATE_DOWNWARD; + stopMachine(); + return false; + } + } + + @Override + public void enableWorking() { + super.enableWorking(); + shutdownReason = ""; + } + + @Override + public void onDisableWorking() { + if (suppressErrorWipe) { + suppressErrorWipe = false; + } else { + super.onDisableWorking(); + } + } + @Override @NotNull public CheckRecipeResult checkProcessing() { @@ -424,34 +512,88 @@ public abstract class GT_MetaTileEntity_DrillerBase // Public pipe actions setElectricityStats(); int oldYHead = yHead; - if (!checkPipesAndSetYHead() || !isEnergyEnough()) { + if (!checkPipesAndSetYHead()) { stopMachine(); return SimpleCheckRecipeResult.ofFailure("no_mining_pipe"); + } else if (!isEnergyEnough()) { + stopMachine(); + return SimpleCheckRecipeResult.ofFailure("not_enough_energy"); } putMiningPipesFromInputsInController(); + + final boolean wasSuccessful; switch (workState) { - case STATE_DOWNWARD -> { - return workingDownward(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead) - ? SimpleCheckRecipeResult.ofSuccess("drilling") - : SimpleCheckRecipeResult.ofFailure("extracting_pipe"); + case STATE_DOWNWARD -> wasSuccessful = workingDownward( + controllerStack, + xDrill, + yDrill, + zDrill, + xPipe, + zPipe, + yHead, + oldYHead); + case STATE_AT_BOTTOM -> wasSuccessful = workingAtBottom( + controllerStack, + xDrill, + yDrill, + zDrill, + xPipe, + zPipe, + yHead, + oldYHead); + case STATE_UPWARD -> wasSuccessful = workingUpward( + controllerStack, + xDrill, + yDrill, + zDrill, + xPipe, + zPipe, + yHead, + oldYHead); + case STATE_ABORT -> wasSuccessful = workingToAbortOperation( + controllerStack, + xDrill, + yDrill, + zDrill, + xPipe, + zPipe, + yHead, + oldYHead); + default -> wasSuccessful = false; + } - } - case STATE_AT_BOTTOM -> { - return workingAtBottom(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead) - ? SimpleCheckRecipeResult.ofSuccess("drilling") - : SimpleCheckRecipeResult.ofFailure("no_mining_pipe"); - } - case STATE_UPWARD -> { - return workingUpward(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead) - ? SimpleCheckRecipeResult.ofSuccess("retracting_pipe") - : SimpleCheckRecipeResult.ofFailure("no_mining_pipe"); - } - default -> { - return SimpleCheckRecipeResult.ofFailure("no_mining_pipe"); - } + if (runtimeFailure == null) { + return resultRegistry.getOrDefault( + new ResultRegistryKey(workState, wasSuccessful), + SimpleCheckRecipeResult.ofFailure("no_mining_pipe")); + } else { + final CheckRecipeResult result; + result = runtimeFailure; + runtimeFailure = null; + return result; } } + /** + * Allow drills to set a specific failure reason specific to their situation. E.g.: out of drilling fluid. + * Should be used when the machine doesn't turn off due to the failure. + * + * @param newFailureReason A new failure reason + */ + protected void setRuntimeFailureReason(@NotNull CheckRecipeResult newFailureReason) { + runtimeFailure = newFailureReason; + } + + /** + * Sets a line in the UI to explain why the drill shut down. E.g.: operation finished. + * Should be used when the machine has been turned off due to an operating issue or completion. + * + * @param newReason The reason for the machine shutdown + */ + protected void setShutdownReason(@NotNull String newReason) { + shutdownReason = newReason; + } + @Override protected IAlignmentLimits getInitialAlignmentLimits() { return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated() @@ -636,6 +778,89 @@ public abstract class GT_MetaTileEntity_DrillerBase return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 6, 0, elementBudget, env, false, true); } + @Override + protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) { + super.drawTexts(screenElements, inventorySlot); + screenElements.widget( + TextWidget.dynamicString(() -> shutdownReason) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled(widget -> !(getBaseMetaTileEntity().isActive() || shutdownReason.isEmpty()))) + .widget(new FakeSyncWidget.StringSyncer(() -> shutdownReason, newString -> shutdownReason = newString)); + } + + /** + * Adds additional buttons to the main button row. You do not need to set the position. + * + * @param builder Only use to attach SyncWidgets. + * @param buildContext Context for things like the player. + */ + protected List<ButtonWidget> getAdditionalButtons(ModularWindow.Builder builder, UIBuildContext buildContext) { + return ImmutableList.of(); + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + super.addUIWidgets(builder, buildContext); + final int BUTTON_Y_LEVEL = 91; + + builder.widget( + new GT_DisabledWhileActiveButton(this.getBaseMetaTileEntity(), builder) + .setOnClick((clickData, widget) -> mChunkLoadingEnabled = !mChunkLoadingEnabled) + .setPlayClickSound(true) + .setBackground(() -> { + if (mChunkLoadingEnabled) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED, + GT_UITextures.OVERLAY_CHUNK_LOADING }; + } + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_CHUNK_LOADING_OFF }; + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer( + () -> mChunkLoadingEnabled, + newBoolean -> mChunkLoadingEnabled = newBoolean), + builder, + (widget, val) -> widget.notifyTooltipChange()) + .dynamicTooltip( + () -> ImmutableList.of( + StatCollector.translateToLocal( + mChunkLoadingEnabled ? "GT5U.gui.button.chunk_loading_on" + : "GT5U.gui.button.chunk_loading_off"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(new Pos2d(80, BUTTON_Y_LEVEL)) + .setSize(16, 16)) + .widget( + new ButtonWidget().setOnClick((clickData, widget) -> abortDrilling()) + .setPlayClickSound(true) + .setBackground(() -> { + if (workState == STATE_ABORT) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED, + GT_UITextures.OVERLAY_RETRACT_PIPE, GT_UITextures.OVERLAY_BUTTON_LOCKED }; + } + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_RETRACT_PIPE }; + }) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer(() -> workState, (newInt) -> workState = newInt), + builder, + (widget, integer) -> widget.notifyTooltipChange()) + .dynamicTooltip( + () -> ImmutableList.of( + StatCollector.translateToLocalFormatted( + workState == STATE_ABORT ? "GT5U.gui.button.drill_retract_pipes_active" + : "GT5U.gui.button.drill_retract_pipes"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(new Pos2d(174, 130)) + .setSize(16, 16)); + + int left = 98; + for (ButtonWidget button : getAdditionalButtons(builder, buildContext)) { + button.setPos(new Pos2d(left, BUTTON_Y_LEVEL)) + .setSize(16, 16); + builder.widget(button); + left += 18; + } + } + protected List<IHatchElement<? super GT_MetaTileEntity_DrillerBase>> getAllowedHatches() { return ImmutableList.of( InputHatch, @@ -667,4 +892,57 @@ public abstract class GT_MetaTileEntity_DrillerBase return t.mDataAccessHatches.size(); } } + + /** + * Sets or overrides the {@link CheckRecipeResult} for a given work state + * + * @param state A work state like {@link #STATE_DOWNWARD}. + * @param result A previously registered recipe result. + */ + protected void addResultMessage(final int state, @NotNull final CheckRecipeResult result) { + resultRegistry.put(new ResultRegistryKey(state, result.wasSuccessful()), result); + } + + /** + * Sets or overrides the {@link CheckRecipeResult} for a given work state and operation success type. + * + * @param state A work state like {@link #STATE_DOWNWARD}. + * @param wasSuccessful Whether the operation was successful. + * @param resultKey An I18N key for the message. + */ + protected void addResultMessage(final int state, final boolean wasSuccessful, @NotNull final String resultKey) { + addResultMessage( + state, + wasSuccessful ? SimpleCheckRecipeResult.ofSuccess(resultKey) + : SimpleCheckRecipeResult.ofFailure(resultKey)); + } + + @SuppressWarnings("ClassCanBeRecord") + private final static class ResultRegistryKey { + + private final int state; + private final boolean successful; + + public ResultRegistryKey(final int state, final boolean successful) { + this.state = state; + this.successful = successful; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ResultRegistryKey other)) { + return false; + } + + return (state == other.state && successful == other.successful); + } + + @Override + public int hashCode() { + return Objects.hash(state, successful); + } + } } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java index 5031a664c7..9a6f2b5e80 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java @@ -29,16 +29,25 @@ import net.minecraft.util.StatCollector; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.NotNull; + import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; import gregtech.api.enums.SoundResource; import gregtech.api.interfaces.IHatchElement; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.objects.GT_ChunkManager; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_Log; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; @@ -207,6 +216,7 @@ public abstract class GT_MetaTileEntity_OilDrillBase extends GT_MetaTileEntity_D if (pumpResult.getType() != ValidationType.VALID) { mEUt = 0; mMaxProgresstime = 0; + setRuntimeFailureReason(CheckRecipeResultRegistry.OUTPUT_FULL); return false; } FluidStack tFluid = pumpResult.getResult(); @@ -217,6 +227,7 @@ public abstract class GT_MetaTileEntity_OilDrillBase extends GT_MetaTileEntity_D } GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity()); workState = STATE_UPWARD; + setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.drill_exhausted")); return true; } @@ -359,24 +370,84 @@ public abstract class GT_MetaTileEntity_OilDrillBase extends GT_MetaTileEntity_D + EnumChatFormatting.RESET, StatCollector.translateToLocal("GT5U.machines.workarea") + ": " + EnumChatFormatting.GREEN - + (chunkRangeConfig) + + GT_Utility.formatNumbers(chunkRangeConfig) + " x " - + (chunkRangeConfig) + + GT_Utility.formatNumbers(chunkRangeConfig) + EnumChatFormatting.RESET + " " + StatCollector.translateToLocal("GT5U.machines.chunks"), - "Drilling fluid: " + EnumChatFormatting.GREEN - + (mOilId > 0 ? FluidRegistry.getFluid(mOilId) - .getName() : "None") - + EnumChatFormatting.RESET, + "Drilling fluid: " + EnumChatFormatting.GREEN + getFluidName() + EnumChatFormatting.RESET, "Drilling flow: " + EnumChatFormatting.GREEN - + GT_Utility.formatNumbers(this.mMaxProgresstime > 0 ? (mOilFlow / this.mMaxProgresstime) : 0) + + getFlowRatePerTick() + EnumChatFormatting.RESET + " L/t")); l.addAll(Arrays.asList(super.getInfoData())); return l.toArray(new String[0]); } + @NotNull + protected String getFlowRatePerTick() { + return GT_Utility.formatNumbers(this.mMaxProgresstime > 0 ? (mOilFlow / this.mMaxProgresstime) : 0); + } + + @NotNull + private String getFluidName() { + if (mOilId > 0) { + final Fluid fluid = FluidRegistry.getFluid(mOilId); + return fluid.getLocalizedName(new FluidStack(fluid, 0)); + } + return "None"; + } + + private @NotNull String clientFluidType = ""; + private @NotNull String clientPumpRate = ""; + private @NotNull String clientReservoirContents = ""; + + @NotNull + private String getReservoirContents() { + int amount = 0; + for (Chunk chunk : mOilFieldChunks) { + final FluidStack fluidStack = undergroundOil(chunk, -1); + if (fluidStack != null) { + amount += fluidStack.amount; + } + } + + return StatCollector.translateToLocalFormatted("GT5U.gui.text.pump_recovery", GT_Utility.formatNumbers(amount)); + } + + @Override + protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) { + super.drawTexts(screenElements, inventorySlot); + screenElements + .widget( + TextWidget + .dynamicString( + () -> StatCollector.translateToLocalFormatted("GT5U.gui.text.pump_fluid_type", clientFluidType)) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM)) + .widget( + TextWidget.dynamicString( + () -> StatCollector + .translateToLocalFormatted("GT5U.gui.text.pump_rate", EnumChatFormatting.AQUA + clientPumpRate)) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM)) + .widget( + TextWidget.dynamicString(() -> clientReservoirContents) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM)) + .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, newInt -> workState = newInt)) + .widget(new FakeSyncWidget.StringSyncer(this::getFluidName, newString -> clientFluidType = newString)) + .widget(new FakeSyncWidget.StringSyncer(this::getFlowRatePerTick, newString -> clientPumpRate = newString)) + .widget( + new FakeSyncWidget.StringSyncer( + this::getReservoirContents, + newString -> clientReservoirContents = newString)); + } + @Override public boolean supportsVoidProtection() { return true; diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java index dd688e3b0d..8103ff632b 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java @@ -6,6 +6,7 @@ import static gregtech.api.enums.GT_HatchElement.InputHatch; import static gregtech.api.enums.GT_HatchElement.Maintenance; import static gregtech.api.enums.GT_HatchElement.OutputBus; import static gregtech.api.enums.GT_Values.VN; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; import java.util.ArrayList; import java.util.Collection; @@ -25,15 +26,29 @@ import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.NotNull; + import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; import gregtech.api.enums.SoundResource; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.gui.widgets.GT_DisabledWhileActiveButton; import gregtech.api.interfaces.IHatchElement; import gregtech.api.objects.GT_ChunkManager; import gregtech.api.objects.ItemData; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.api.util.GT_OreDictUnificator; import gregtech.api.util.GT_Recipe; @@ -48,6 +63,18 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile private int chunkRadiusConfig = getRadiusInChunks(); private boolean replaceWithCobblestone = true; + /** Used to drive the remaining ores count in the UI. */ + private int clientOreListSize = 0; + + /** Used to drive the current chunk number in the UI. */ + private int clientCurrentChunk = 0; + + /** Used to drive the total chunk count in the UI. */ + private int clientTotalChunks = 0; + + /** Used to drive the drill's y-level in the UI. */ + private int clientYHead = 0; + GT_MetaTileEntity_OreDrillingPlantBase(int aID, String aName, String aNameRegional) { super(aID, aName, aNameRegional); } @@ -74,26 +101,42 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile } } - @Override - public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { - super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ); - if (aPlayer.isSneaking()) { + private void adjustChunkRadius(boolean increase) { + if (increase) { + if (chunkRadiusConfig <= getRadiusInChunks()) { + chunkRadiusConfig++; + } + if (chunkRadiusConfig > getRadiusInChunks()) chunkRadiusConfig = 1; + } else { if (chunkRadiusConfig > 0) { chunkRadiusConfig--; } if (chunkRadiusConfig == 0) chunkRadiusConfig = getRadiusInChunks(); + } + + if (mCurrentChunk != null && mChunkLoadingEnabled) { + GT_ChunkManager.releaseChunk((TileEntity) getBaseMetaTileEntity(), mCurrentChunk); + } + + oreBlockPositions.clear(); + createInitialWorkingChunk(); + } + + @Override + public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { + super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ); + + if (getBaseMetaTileEntity().isActive()) { + GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("GT5U.machines.workarea_fail")); } else { - if (chunkRadiusConfig <= getRadiusInChunks()) { - chunkRadiusConfig++; - } - if (chunkRadiusConfig > getRadiusInChunks()) chunkRadiusConfig = 1; + adjustChunkRadius(!aPlayer.isSneaking()); + GT_Utility.sendChatToPlayer( + aPlayer, + StatCollector.translateToLocal("GT5U.machines.workareaset") + " " + + GT_Utility.formatNumbers((long) chunkRadiusConfig << 4) + + " " + + StatCollector.translateToLocal("GT5U.machines.radius")); } - GT_Utility.sendChatToPlayer( - aPlayer, - StatCollector.translateToLocal("GT5U.machines.workareaset") + " " - + (chunkRadiusConfig << 4) - + " " - + StatCollector.translateToLocal("GT5U.machines.radius")); } @Override @@ -118,6 +161,7 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile switch (tryLowerPipeState()) { case 2 -> { mMaxProgresstime = 0; + setRuntimeFailureReason(CheckRecipeResultRegistry.MISSING_MINING_PIPE); return false; } case 3 -> { @@ -177,6 +221,7 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile if (!tryConsumeDrillingFluid(simulate)) { oreBlockPositions.add(0, oreBlockPos); + setRuntimeFailureReason(CheckRecipeResultRegistry.NO_DRILLING_FLUID); return false; } if (oreBlock != null && GT_Utility.isOre(oreBlock, oreBlockMetadata)) { @@ -199,6 +244,7 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile } ItemStack[] toOutput = getOutputByDrops(oreBlockDrops); if (simulate && !canOutputAll(toOutput)) { + setRuntimeFailureReason(CheckRecipeResultRegistry.OUTPUT_FULL); return false; } mOutputItems = toOutput; @@ -242,28 +288,109 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile } private void createInitialWorkingChunk() { - final int centerX = getXDrill() >> 4; - final int centerZ = getZDrill() >> 4; + mCurrentChunk = getTopLeftChunkCoords(); + if (mChunkLoadingEnabled) { + GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), mCurrentChunk); + mWorkChunkNeedsReload = false; + } + } + + @NotNull + private ChunkCoordIntPair getTopLeftChunkCoords() { + return getCornerCoords(-1, -1); + } + + @NotNull + private ChunkCoordIntPair getBottomRightChunkCoords() { + return getCornerCoords(1, 1); + } + + @NotNull + private ChunkCoordIntPair getCornerCoords(int xMultiplier, int zMultiplier) { + final ChunkCoordIntPair drillPos = getDrillCoords(); // use corner closest to the drill as mining area center - final int leftRight = (getXDrill() - (centerX << 4)) < 8 ? 0 : 1; - final int topBottom = (getZDrill() - (centerZ << 4)) < 8 ? 0 : 1; - mCurrentChunk = new ChunkCoordIntPair( - centerX - chunkRadiusConfig + leftRight, - centerZ - chunkRadiusConfig + topBottom); - GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), mCurrentChunk); - mWorkChunkNeedsReload = false; + return new ChunkCoordIntPair( + drillPos.chunkXPos + xMultiplier * chunkRadiusConfig + + ((getXDrill() - (drillPos.chunkXPos << 4)) < 8 ? 0 : 1), + drillPos.chunkZPos + zMultiplier * chunkRadiusConfig + + ((getZDrill() - (drillPos.chunkZPos << 4)) < 8 ? 0 : 1)); + } + + @NotNull + private ChunkCoordIntPair getDrillCoords() { + return new ChunkCoordIntPair(getXDrill() >> 4, getZDrill() >> 4); + } + + private int getTotalChunkCount() { + final ChunkCoordIntPair topLeft = getTopLeftChunkCoords(); + final ChunkCoordIntPair bottomRight = getBottomRightChunkCoords(); + return (bottomRight.chunkXPos - topLeft.chunkXPos) * (bottomRight.chunkZPos - topLeft.chunkZPos); + } + + /** + * Returns a number corresponding to which chunk the drill is operating on. Only really useful for driving outputs + * in the controller UI. + * + * @return 0 if the miner is not in operation, positive integer corresponding to the chunk currently being drilled + */ + @SuppressWarnings("ExtractMethodRecommender") + private int getChunkNumber() { + if (mCurrentChunk == null) { + return 0; + } + + final ChunkCoordIntPair topLeft = getTopLeftChunkCoords(); + final ChunkCoordIntPair drillPos = getDrillCoords(); + + if (workState == STATE_DOWNWARD) { + return 1; + } else if (workState == STATE_UPWARD) { + // Technically, the miner isn't mining anything now; it's retracting the pipes in preparation to end + // operation. + return 0; + } + + int chunkNumber = (chunkRadiusConfig * 2) * (mCurrentChunk.chunkZPos - topLeft.chunkZPos) + + mCurrentChunk.chunkXPos + - topLeft.chunkXPos + + 1; + + // Drills mine the chunk they're in first, so if we're not there yet, bump the number to indicate that it + // was already mined. + if (mCurrentChunk.chunkZPos < drillPos.chunkZPos + || (mCurrentChunk.chunkZPos == drillPos.chunkZPos && mCurrentChunk.chunkXPos < drillPos.chunkXPos)) { + chunkNumber += 1; + } + return chunkNumber; } @Override protected boolean workingUpward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead, int oldYHead) { - if (!mChunkLoadingEnabled || oreBlockPositions.isEmpty()) - return super.workingUpward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead); - boolean result = tryProcessOreList(); - if (oreBlockPositions.isEmpty()) GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity()); + boolean result; + if (!mChunkLoadingEnabled || oreBlockPositions.isEmpty()) { + result = super.workingUpward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead); + } else { + result = tryProcessOreList(); + if (oreBlockPositions.isEmpty()) GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity()); + } + + if (!result) { + setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.drill_exhausted")); + } + return result; } + @Override + protected void onAbort() { + oreBlockPositions.clear(); + if (mCurrentChunk != null) { + GT_ChunkManager.releaseChunk((TileEntity) getBaseMetaTileEntity(), mCurrentChunk); + } + mCurrentChunk = null; + } + private boolean moveToNextChunk(int centerX, int centerZ) { if (mCurrentChunk == null) return false; // use corner closest to the drill as mining area center @@ -449,13 +576,102 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile } @Override + protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) { + super.drawTexts(screenElements, inventorySlot); + screenElements + .widget( + TextWidget + .dynamicString( + () -> StatCollector.translateToLocalFormatted( + "GT5U.gui.text.drill_ores_left_chunk", + GT_Utility.formatNumbers(clientOreListSize))) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled( + widget -> getBaseMetaTileEntity().isActive() && clientOreListSize > 0 + && workState == STATE_AT_BOTTOM)) + .widget( + TextWidget + .dynamicString( + () -> StatCollector.translateToLocalFormatted( + "GT5U.gui.text.drill_ores_left_layer", + GT_Utility.formatNumbers(clientYHead), + GT_Utility.formatNumbers(clientOreListSize))) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled( + widget -> getBaseMetaTileEntity().isActive() && clientYHead > 0 && workState == STATE_DOWNWARD)) + .widget( + TextWidget + .dynamicString( + () -> StatCollector.translateToLocalFormatted( + "GT5U.gui.text.drill_chunks_left", + GT_Utility.formatNumbers(clientCurrentChunk), + GT_Utility.formatNumbers(clientTotalChunks))) + .setSynced(false) + .setTextAlignment(Alignment.CenterLeft) + .setEnabled( + widget -> getBaseMetaTileEntity().isActive() && clientCurrentChunk > 0 + && workState == STATE_AT_BOTTOM)) + .widget(new FakeSyncWidget.IntegerSyncer(oreBlockPositions::size, (newInt) -> clientOreListSize = newInt)) + .widget(new FakeSyncWidget.IntegerSyncer(this::getTotalChunkCount, (newInt) -> clientTotalChunks = newInt)) + .widget(new FakeSyncWidget.IntegerSyncer(this::getChunkNumber, (newInt) -> clientCurrentChunk = newInt)) + .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, (newInt) -> workState = newInt)) + .widget(new FakeSyncWidget.IntegerSyncer(this::getYHead, (newInt) -> clientYHead = newInt)); + } + + @Override + protected List<ButtonWidget> getAdditionalButtons(ModularWindow.Builder builder, UIBuildContext buildContext) { + return ImmutableList.of( + (ButtonWidget) new GT_DisabledWhileActiveButton(this.getBaseMetaTileEntity(), builder) + .setOnClick((clickData, widget) -> adjustChunkRadius(clickData.mouseButton == 0)) + .setPlayClickSound(true) + .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_WORK_AREA) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer(() -> chunkRadiusConfig, (val) -> chunkRadiusConfig = val), + builder, + (widget, val) -> widget.notifyTooltipChange()) + .dynamicTooltip( + () -> ImmutableList.of( + StatCollector.translateToLocalFormatted( + "GT5U.gui.button.ore_drill_radius_1", + GT_Utility.formatNumbers((long) chunkRadiusConfig << 4)), + StatCollector.translateToLocal("GT5U.gui.button.ore_drill_radius_2"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(16, 16), + (ButtonWidget) new GT_DisabledWhileActiveButton(this.getBaseMetaTileEntity(), builder) + .setOnClick((clickData, widget) -> replaceWithCobblestone = !replaceWithCobblestone) + .setPlayClickSound(true) + .setBackground(() -> { + if (replaceWithCobblestone) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, + GT_UITextures.OVERLAY_REPLACE_COBBLE_ON }; + } + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_REPLACE_COBBLE_OFF }; + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer( + () -> replaceWithCobblestone, + (val) -> replaceWithCobblestone = val), + builder, + (widget, val) -> widget.notifyTooltipChange()) + .dynamicTooltip( + () -> ImmutableList.of( + StatCollector.translateToLocal( + replaceWithCobblestone ? "GT5U.gui.button.ore_drill_cobblestone_on" + : "GT5U.gui.button.ore_drill_cobblestone_off"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(16, 16)); + } + + @Override protected SoundResource getProcessStartSound() { return SoundResource.IC2_MACHINES_MINER_OP; } @Override public String[] getInfoData() { - final int diameter = chunkRadiusConfig * 2; + final String diameter = GT_Utility.formatNumbers(chunkRadiusConfig * 2L); return new String[] { EnumChatFormatting.BLUE + StatCollector.translateToLocal("GT5U.machines.minermulti") + EnumChatFormatting.RESET, diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang index dc67ba0531..ab69f948da 100644 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ b/src/main/resources/assets/gregtech/lang/en_US.lang @@ -192,6 +192,7 @@ gt.recipe.wiremill.description=Produces Wires more efficiently GT5U.machines.tier=Tier GT5U.machines.workarea=Work Area GT5U.machines.workareaset=Work Area set to +GT5U.machines.workarea_fail=Can't adjust work area while running GT5U.machines.autoretract.enabled=Auto retract enabled GT5U.machines.autoretract.disabled=Auto retract disabled GT5U.machines.radius=radius @@ -351,6 +352,15 @@ GT5U.gui.button.lock_recipe=Lock Recipe GT5U.gui.button.down_tier=Down Tier GT5U.gui.button.tier=Tier: GT5U.gui.button.forbidden=§4Cannot change mode for this machine +GT5U.gui.button.forbidden_while_running=§4Cannot change mode while running +GT5U.gui.button.chunk_loading_on=§7Chunk Loading: §aON +GT5U.gui.button.chunk_loading_off=§7Chunk Loading: §4OFF +GT5U.gui.button.ore_drill_radius_1=§7Current Radius: §a%s +GT5U.gui.button.ore_drill_radius_2=§7Left-click to increment, right-click to decrement +GT5U.gui.button.ore_drill_cobblestone_on=§7Replace with cobblestone: §aON +GT5U.gui.button.ore_drill_cobblestone_off=§7Replace with cobblestone: §4OFF +GT5U.gui.button.drill_retract_pipes=§7Abort and retract mining pipes +GT5U.gui.button.drill_retract_pipes_active=§4Cannot interrupt abort procedure GT5U.gui.text.success=§aProcessing recipe GT5U.gui.text.generating=§aGenerating power GT5U.gui.text.no_recipe=§7No valid recipe found @@ -369,8 +379,21 @@ GT5U.gui.text.machine_mismatch=§7Machine doesn't match to locked recipe GT5U.gui.text.high_gravity=§7Recipe needs low gravity GT5U.gui.text.no_mining_pipe=§7Missing Mining Pipe GT5U.gui.text.drilling=§aDrilling +GT5U.gui.text.deploying_pipe=§aDeploying mining pipe GT5U.gui.text.extracting_pipe=§aExtracting pipe GT5U.gui.text.retracting_pipe=§aRetracting pipe +GT5U.gui.text.no_drilling_fluid=§7No drilling fluid +GT5U.gui.text.drill_exhausted=§dDrill has exhausted all resources +GT5U.gui.text.drill_generic_finished=§7Mining pipes have been retracted +GT5U.gui.text.drill_retract_pipes_finished=§7Operation aborted +GT5U.gui.text.backfiller_no_concrete=§7No liquid concrete +GT5U.gui.text.backfiller_finished=§aWork complete +GT5U.gui.text.backfiller_working=§aPouring concrete +GT5U.gui.text.backfiller_current_area=§7Filling at y-level: §a%s +GT5U.gui.text.pump_fluid_type=§7Fluid: §a%s +GT5U.gui.text.pump_rate=§7Pumping rate: %s§7 L/t +GT5U.gui.text.pump_recovery=§7Recovering §b%s§7 L per operation +GT5U.gui.text.not_enough_energy=§7Not enough energy GT5U.gui.text.power_overflow=§7Power overflowed GT5U.gui.text.duration_overflow=§7Processing time overflowed GT5U.gui.text.insufficient_power=§7Recipe needs more power to start. Required: %s EU/t (%s§7) @@ -378,6 +401,9 @@ GT5U.gui.text.insufficient_heat=§7Recipe needs more heat to start. Required: %s GT5U.gui.text.insufficient_machine_tier=§7Recipe needs higher structure tier. Required: %s GT5U.gui.text.insufficient_startup_power=§7Recipe needs higher startup power. Required: %s GT5U.gui.text.internal_error=§4Recipe was found, but had internal error +GT5U.gui.text.drill_ores_left_chunk=§7Ores left in current chunk: §a%s +GT5U.gui.text.drill_ores_left_layer=§7Ores left at y-level %s: §a%s +GT5U.gui.text.drill_chunks_left=§7Drilling chunk: §a%s / %s GT5U.item.programmed_circuit.select.header=Reprogram Circuit diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading.png Binary files differnew file mode 100644 index 0000000000..bfd288be45 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading_off.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading_off.png Binary files differnew file mode 100644 index 0000000000..db75847e0c --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading_off.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/lock_small.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/lock_small.png Binary files differnew file mode 100644 index 0000000000..3b8c8ab0f5 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/lock_small.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_off.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_off.png Binary files differnew file mode 100644 index 0000000000..8b968a3413 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_off.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_on.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_on.png Binary files differnew file mode 100644 index 0000000000..45793d5470 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_on.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/retract_pipes.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/retract_pipes.png Binary files differnew file mode 100644 index 0000000000..f67fe157c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/retract_pipes.png diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay_button/work_area.png b/src/main/resources/assets/gregtech/textures/gui/overlay_button/work_area.png Binary files differnew file mode 100644 index 0000000000..10d6478721 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/work_area.png |