aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorquerns <33518699+querns@users.noreply.github.com>2023-09-08 15:39:21 -0500
committerGitHub <noreply@github.com>2023-09-08 22:39:21 +0200
commit7f837715a8377b24853bf0fea02f23c210b47cfc (patch)
treeab75df3f15857a83ee653750cb5090225a7c089d /src/main
parente4f17b7b40503fd34d9dae447802453480b9577c (diff)
downloadGT5-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')
-rw-r--r--src/main/java/gregtech/api/gui/modularui/GT_UITextures.java13
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_DisabledWhileActiveButton.java104
-rw-r--r--src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java7
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java39
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java318
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java85
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java272
-rw-r--r--src/main/resources/assets/gregtech/lang/en_US.lang26
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading.pngbin0 -> 1573 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading_off.pngbin0 -> 1599 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/lock_small.pngbin0 -> 2211 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_off.pngbin0 -> 768 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_on.pngbin0 -> 705 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/retract_pipes.pngbin0 -> 1042 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/gui/overlay_button/work_area.pngbin0 -> 770 bytes
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
new file mode 100644
index 0000000000..bfd288be45
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading.png
Binary files differ
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
new file mode 100644
index 0000000000..db75847e0c
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/chunkloading_off.png
Binary files differ
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
new file mode 100644
index 0000000000..3b8c8ab0f5
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/lock_small.png
Binary files differ
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
new file mode 100644
index 0000000000..8b968a3413
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_off.png
Binary files differ
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
new file mode 100644
index 0000000000..45793d5470
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/replace_cobble_on.png
Binary files differ
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
new file mode 100644
index 0000000000..f67fe157c7
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/retract_pipes.png
Binary files differ
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
new file mode 100644
index 0000000000..10d6478721
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/gui/overlay_button/work_area.png
Binary files differ