aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api')
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java5
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java10
-rw-r--r--src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java16
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java3
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java10
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java77
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java10
-rw-r--r--src/main/java/gregtech/api/util/shutdown/ReasonOutOfFluid.java63
-rw-r--r--src/main/java/gregtech/api/util/shutdown/ReasonOutOfItem.java62
-rw-r--r--src/main/java/gregtech/api/util/shutdown/ReasonOutOfStuff.java61
-rw-r--r--src/main/java/gregtech/api/util/shutdown/ShutDownReason.java41
-rw-r--r--src/main/java/gregtech/api/util/shutdown/ShutDownReasonRegistry.java118
-rw-r--r--src/main/java/gregtech/api/util/shutdown/SimpleShutDownReason.java79
13 files changed, 535 insertions, 20 deletions
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java b/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java
index cf39f4c22a..d8231ee544 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java
@@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nonnull;
+
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@@ -19,6 +21,7 @@ import gregtech.api.interfaces.IDescribable;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.modularui.IAddInventorySlots;
import gregtech.api.interfaces.modularui.IGetGUITextureSet;
+import gregtech.api.util.shutdown.ShutDownReason;
import gregtech.common.blocks.GT_Block_Machines;
/**
@@ -179,6 +182,8 @@ public interface IGregTechTileEntity extends ITexturedTileEntity, IGearEnergyTil
default void setShutdownStatus(boolean newStatus) {}
+ default void setShutDownReason(@Nonnull ShutDownReason reason) {}
+
/**
* A randomly called display update to be able to add particles or other items for display The event is proxied by
* the {@link GT_Block_Machines#randomDisplayTick}
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java b/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
index 517f4a0cd3..83570fedcc 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
@@ -1,5 +1,10 @@
package gregtech.api.interfaces.tileentity;
+import javax.annotation.Nonnull;
+
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+
/**
* For Machines which have Progress
*/
@@ -83,4 +88,9 @@ public interface IMachineProgress extends IHasWorldObjectAndCoords {
default boolean wasShutdown() {
return false;
}
+
+ @Nonnull
+ default ShutDownReason getLastShutDownReason() {
+ return ShutDownReasonRegistry.NONE;
+ }
}
diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
index e387d3cd5a..61728d9267 100644
--- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
@@ -12,6 +12,7 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
@@ -36,6 +37,8 @@ import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
@@ -78,6 +81,8 @@ import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_OreDictUnificator;
import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
import gregtech.common.GT_Pollution;
import gregtech.common.covers.CoverInfo;
import ic2.api.Direction;
@@ -101,6 +106,7 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
private boolean hasTimeStatisticsStarted;
public long mLastSoundTick = 0;
public boolean mWasShutdown = false;
+ public @Nonnull ShutDownReason lastShutDownReason = ShutDownReasonRegistry.NONE;
protected MetaTileEntity mMetaTileEntity;
protected long mStoredEnergy = 0, mStoredSteam = 0;
protected int mAverageEUInputIndex = 0, mAverageEUOutputIndex = 0;
@@ -2469,6 +2475,16 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
}
@Override
+ public void setShutDownReason(@NotNull ShutDownReason reason) {
+ lastShutDownReason = reason;
+ }
+
+ @Override
+ public @NotNull ShutDownReason getLastShutDownReason() {
+ return lastShutDownReason;
+ }
+
+ @Override
public IAlignment getAlignment() {
return getMetaTileEntity() instanceof IAlignmentProvider
? ((IAlignmentProvider) getMetaTileEntity()).getAlignment()
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java
index cc585d1999..c7f0e6cdd5 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java
@@ -22,6 +22,7 @@ import cpw.mods.fml.common.network.NetworkRegistry;
import gregtech.api.GregTech_API;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
/**
* Enhanced multiblock base class, featuring following improvement over {@link GT_MetaTileEntity_MultiBlockBase}
@@ -53,7 +54,7 @@ public abstract class GT_MetaTileEntity_EnhancedMultiBlockBase<T extends GT_Meta
@Override
public void setExtendedFacing(ExtendedFacing newExtendedFacing) {
if (mExtendedFacing != newExtendedFacing) {
- if (mMachine) stopMachine();
+ if (mMachine) stopMachine(ShutDownReasonRegistry.STRUCTURE_INCOMPLETE);
mExtendedFacing = newExtendedFacing;
final IGregTechTileEntity base = getBaseMetaTileEntity();
mMachine = false;
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
index 6f351fb5ab..b7f34f264c 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
@@ -16,12 +16,16 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
+import org.jetbrains.annotations.NotNull;
+
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.logic.ProcessingLogic;
import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.util.GT_ExoticEnergyInputHelper;
import gregtech.api.util.GT_OverclockCalculator;
import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
/**
* Multiblock base class that allows machine to use power over int.
@@ -72,7 +76,7 @@ public abstract class GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T extends GT
}
if (this.lEUt < 0) {
if (!drainEnergyInput(getActualEnergyUsage())) {
- criticalStopMachine();
+ stopMachine(ShutDownReasonRegistry.POWER_LOSS);
return false;
}
}
@@ -80,9 +84,9 @@ public abstract class GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T extends GT
}
@Override
- public void stopMachine() {
+ public void stopMachine(@NotNull ShutDownReason reason) {
this.lEUt = 0;
- super.stopMachine();
+ super.stopMachine(reason);
}
@Override
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
index 19fee8f153..2bbd99a36a 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
@@ -88,9 +88,12 @@ import gregtech.api.util.GT_Utility;
import gregtech.api.util.GT_Waila;
import gregtech.api.util.OutputHatchWrapper;
import gregtech.api.util.VoidProtectionHelper;
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
import gregtech.client.GT_SoundLoop;
import gregtech.common.GT_Pollution;
import gregtech.common.gui.modularui.widget.CheckRecipeResultSyncer;
+import gregtech.common.gui.modularui.widget.ShutDownReasonSyncer;
import gregtech.common.items.GT_MetaGenerated_Tool_01;
import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_InputBus_ME;
import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_Input_ME;
@@ -402,11 +405,11 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
checkMaintenance();
if (getRepairStatus() > 0) {
runMachine(aBaseMetaTileEntity, aTick);
- } else {
- stopMachine();
+ } else if (aBaseMetaTileEntity.isAllowedToWork()) {
+ stopMachine(ShutDownReasonRegistry.NO_REPAIR);
}
- } else {
- stopMachine();
+ } else if (aBaseMetaTileEntity.isAllowedToWork()) {
+ stopMachine(ShutDownReasonRegistry.STRUCTURE_INCOMPLETE);
}
}
aBaseMetaTileEntity.setErrorDisplayID(
@@ -520,7 +523,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
if (onRunningTick(mInventory[1])) {
markDirty();
if (!polluteEnvironment(getPollutionPerTick(mInventory[1]))) {
- stopMachine();
+ stopMachine(ShutDownReasonRegistry.POLLUTION_FAIL);
}
if (mMaxProgresstime > 0 && ++mProgresstime >= mMaxProgresstime) {
if (mOutputItems != null) {
@@ -668,7 +671,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
}
if (mEUt < 0) {
if (!drainEnergyInput(getActualEnergyUsage())) {
- criticalStopMachine();
+ stopMachine(ShutDownReasonRegistry.POWER_LOSS);
return false;
}
}
@@ -896,7 +899,26 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
*/
public abstract boolean explodesOnComponentBreak(ItemStack aStack);
+ /**
+ * @deprecated Use {@link #stopMachine(ShutDownReason)}
+ */
+ @Deprecated
public void stopMachine() {
+ stopMachine(ShutDownReasonRegistry.NONE);
+ }
+
+ /**
+ * @deprecated Use {@link #stopMachine(ShutDownReason)}
+ */
+ @Deprecated
+ public void criticalStopMachine() {
+ stopMachine(ShutDownReasonRegistry.CRITICAL_NONE);
+ }
+
+ public void stopMachine(@Nonnull ShutDownReason reason) {
+ if (!ShutDownReasonRegistry.isRegistered(reason.getID())) {
+ throw new RuntimeException(String.format("Reason %s is not registered for registry", reason.getID()));
+ }
mOutputItems = null;
mOutputFluids = null;
mEUt = 0;
@@ -905,12 +927,11 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
mMaxProgresstime = 0;
mEfficiencyIncrease = 0;
getBaseMetaTileEntity().disableWorking();
- }
-
- public void criticalStopMachine() {
- stopMachine();
- sendSound(INTERRUPT_SOUND_INDEX);
+ getBaseMetaTileEntity().setShutDownReason(reason);
getBaseMetaTileEntity().setShutdownStatus(true);
+ if (reason.wasCritical()) {
+ sendSound(INTERRUPT_SOUND_INDEX);
+ }
}
public int getRepairStatus() {
@@ -931,8 +952,12 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
}
public boolean doRandomMaintenanceDamage() {
- if (!isCorrectMachinePart(mInventory[1]) || getRepairStatus() == 0) {
- stopMachine();
+ if (!isCorrectMachinePart(mInventory[1])) {
+ stopMachine(ShutDownReasonRegistry.NO_MACHINE_PART);
+ return false;
+ }
+ if (getRepairStatus() == 0) {
+ stopMachine(ShutDownReasonRegistry.NO_REPAIR);
return false;
}
if (mRuntime++ > 1000) {
@@ -2184,6 +2209,10 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
return true;
}
+ protected boolean shouldDisplayShutDownReason() {
+ return true;
+ }
+
protected String generateCurrentRecipeInfoString() {
StringBuilder ret = new StringBuilder(EnumChatFormatting.WHITE + "Progress: ")
.append(String.format("%,.2f", (double) mProgresstime / 20))
@@ -2324,6 +2353,28 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
new TextWidget(GT_Utility.trans("142", "Running perfectly.")).setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(
widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0 && getBaseMetaTileEntity().isActive()));
+
+ screenElements.widget(
+ TextWidget.dynamicString(
+ () -> getBaseMetaTileEntity().getLastShutDownReason()
+ .getDisplayString())
+ .setSynced(false)
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(
+ widget -> shouldDisplayShutDownReason() && !getBaseMetaTileEntity().isActive()
+ && GT_Utility.isStringValid(
+ getBaseMetaTileEntity().getLastShutDownReason()
+ .getDisplayString())
+ && getBaseMetaTileEntity().wasShutdown()))
+ .widget(
+ new ShutDownReasonSyncer(
+ () -> getBaseMetaTileEntity().getLastShutDownReason(),
+ reason -> getBaseMetaTileEntity().setShutDownReason(reason)))
+ .widget(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> getBaseMetaTileEntity().wasShutdown(),
+ wasShutDown -> getBaseMetaTileEntity().setShutdownStatus(wasShutDown)));
+
screenElements.widget(
TextWidget.dynamicString(() -> checkRecipeResult.getDisplayString())
.setSynced(false)
diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java
index 467e52a1db..62c4498927 100644
--- a/src/main/java/gregtech/api/util/GT_Utility.java
+++ b/src/main/java/gregtech/api/util/GT_Utility.java
@@ -3720,11 +3720,15 @@ public class GT_Utility {
int rEUAmount = 0;
try {
if (tTileEntity instanceof IMachineProgress progress) {
- if (progress.isAllowedToWork()) {
+ if (progress.isAllowedToWork() && !progress.hasThingsToDo()) {
tList.add(EnumChatFormatting.RED + "Disabled." + EnumChatFormatting.RESET);
}
- if (progress.wasShutdown()) {
- tList.add(EnumChatFormatting.RED + "Shut down due to power loss." + EnumChatFormatting.RESET);
+ if (progress.wasShutdown() && isStringValid(
+ progress.getLastShutDownReason()
+ .getDisplayString())) {
+ tList.add(
+ progress.getLastShutDownReason()
+ .getDisplayString());
}
rEUAmount += 400;
int tValue = 0;
diff --git a/src/main/java/gregtech/api/util/shutdown/ReasonOutOfFluid.java b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfFluid.java
new file mode 100644
index 0000000000..29b99a644a
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfFluid.java
@@ -0,0 +1,63 @@
+package gregtech.api.util.shutdown;
+
+import static gregtech.api.util.GT_ModHandler.getWater;
+import static gregtech.api.util.GT_Utility.formatNumbers;
+
+import java.util.Objects;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ReasonOutOfFluid implements ShutDownReason {
+
+ private FluidStack requiredFluid;
+
+ ReasonOutOfFluid(@NotNull FluidStack requiredFluid) {
+ this.requiredFluid = requiredFluid;
+ }
+
+ @NotNull
+ @Override
+ public String getID() {
+ return "out_of_fluid";
+ }
+
+ @NotNull
+ @Override
+ public String getDisplayString() {
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.out_of_fluid",
+ requiredFluid.getLocalizedName(),
+ formatNumbers(requiredFluid.amount)));
+ }
+
+ @NotNull
+ @Override
+ public ShutDownReason newInstance() {
+ return new ReasonOutOfFluid(getWater(0));
+ }
+
+ @Override
+ public void encode(@NotNull PacketBuffer buffer) {
+ buffer.writeInt(requiredFluid.getFluidID());
+ buffer.writeInt(requiredFluid.amount);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ int fluidID = buffer.readInt();
+ Fluid fluid = FluidRegistry.getFluid(fluidID);
+ requiredFluid = new FluidStack(fluid, buffer.readInt());
+ }
+
+ @Override
+ public boolean wasCritical() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/util/shutdown/ReasonOutOfItem.java b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfItem.java
new file mode 100644
index 0000000000..f4a46f2d30
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfItem.java
@@ -0,0 +1,62 @@
+package gregtech.api.util.shutdown;
+
+import static gregtech.api.util.GT_Utility.formatNumbers;
+
+import java.util.Objects;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ReasonOutOfItem implements ShutDownReason {
+
+ private ItemStack requiredItem;
+
+ ReasonOutOfItem(@NotNull ItemStack requiredItem) {
+ this.requiredItem = requiredItem;
+ }
+
+ @NotNull
+ @Override
+ public String getID() {
+ return "out_of_item";
+ }
+
+ @NotNull
+ @Override
+ public String getDisplayString() {
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.out_of_item",
+ requiredItem.getDisplayName(),
+ formatNumbers(requiredItem.stackSize)));
+ }
+
+ @NotNull
+ @Override
+ public ShutDownReason newInstance() {
+ return new ReasonOutOfItem(new ItemStack(Items.feather, 0));
+ }
+
+ @Override
+ public void encode(@NotNull PacketBuffer buffer) {
+ try {
+ buffer.writeItemStackToBuffer(requiredItem);
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ try {
+ requiredItem = buffer.readItemStackFromBuffer();
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public boolean wasCritical() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/util/shutdown/ReasonOutOfStuff.java b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfStuff.java
new file mode 100644
index 0000000000..0c3f7e0b64
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/ReasonOutOfStuff.java
@@ -0,0 +1,61 @@
+package gregtech.api.util.shutdown;
+
+import static gregtech.api.util.GT_Utility.formatNumbers;
+
+import java.util.Objects;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ReasonOutOfStuff implements ShutDownReason {
+
+ private String required;
+ private int amount;
+
+ ReasonOutOfStuff(@NotNull String required, int amount) {
+ this.required = required;
+ this.amount = amount;
+ }
+
+ @NotNull
+ @Override
+ public String getID() {
+ return "out_of_stuff";
+ }
+
+ @NotNull
+ @Override
+ public String getDisplayString() {
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted("GT5U.gui.text.out_of_stuff", required, formatNumbers(amount)));
+ }
+
+ @NotNull
+ @Override
+ public ShutDownReason newInstance() {
+ return new ReasonOutOfStuff("stuff", 1);
+ }
+
+ @Override
+ public void encode(@NotNull PacketBuffer buffer) {
+ buffer.writeInt(amount);
+ try {
+ buffer.writeStringToBuffer(required);
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ amount = buffer.readInt();
+ try {
+ required = buffer.readStringFromBuffer(32768);
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public boolean wasCritical() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/util/shutdown/ShutDownReason.java b/src/main/java/gregtech/api/util/shutdown/ShutDownReason.java
new file mode 100644
index 0000000000..0815936a55
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/ShutDownReason.java
@@ -0,0 +1,41 @@
+package gregtech.api.util.shutdown;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.network.PacketBuffer;
+
+public interface ShutDownReason {
+
+ /**
+ * @return Unique registry ID
+ */
+ @Nonnull
+ String getID();
+
+ /**
+ * @return Actual text to show on client GUI
+ */
+ @Nonnull
+ String getDisplayString();
+
+ /**
+ * Create new instance to receive packet.
+ */
+ @Nonnull
+ ShutDownReason newInstance();
+
+ /**
+ * Encode value to sync.
+ */
+ void encode(@Nonnull PacketBuffer buffer);
+
+ /**
+ * Decode synced value.
+ */
+ void decode(PacketBuffer buffer);
+
+ /**
+ * @return Whether the reason is critical.
+ */
+ boolean wasCritical();
+}
diff --git a/src/main/java/gregtech/api/util/shutdown/ShutDownReasonRegistry.java b/src/main/java/gregtech/api/util/shutdown/ShutDownReasonRegistry.java
new file mode 100644
index 0000000000..298c5db237
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/ShutDownReasonRegistry.java
@@ -0,0 +1,118 @@
+package gregtech.api.util.shutdown;
+
+import static gregtech.api.util.GT_ModHandler.getWater;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+public class ShutDownReasonRegistry {
+
+ private static final Map<String, ShutDownReason> registry = new HashMap<>();
+
+ /**
+ * Registers ShutDownReason. No duplicated IDs are allowed.
+ *
+ * @param sample Sample object to register
+ */
+ public static void register(ShutDownReason sample) {
+ if (isRegistered(sample.getID())) {
+ throw new IllegalStateException(
+ String.format(
+ "ID %s is already registered for %s",
+ sample.getID(),
+ registry.get(sample.getID())
+ .getClass()
+ .getCanonicalName()));
+ }
+ registry.put(sample.getID(), sample);
+ }
+
+ public static ShutDownReason getSampleFromRegistry(String id) {
+ if (!isRegistered(id)) {
+ throw new RuntimeException("Unknown id: " + id);
+ }
+ return registry.get(id);
+ }
+
+ public static boolean isRegistered(String id) {
+ return registry.containsKey(id);
+ }
+
+ /**
+ * Shut down due to power loss.
+ */
+ @Nonnull
+ public static final ShutDownReason POWER_LOSS = SimpleShutDownReason.ofCritical("power_loss");
+ /**
+ * Failed to output the pollution.
+ */
+ @Nonnull
+ public static final ShutDownReason POLLUTION_FAIL = SimpleShutDownReason.ofCritical("pollution_fail");
+ /**
+ * Shut down due to incomplete structure.
+ */
+ @Nonnull
+ public static final ShutDownReason STRUCTURE_INCOMPLETE = SimpleShutDownReason.ofNormal("structure_incomplete");
+ /**
+ * Shut down due to machine damage.
+ */
+ @Nonnull
+ public static final ShutDownReason NO_REPAIR = SimpleShutDownReason.ofNormal("no_repair");
+ /**
+ * No valid turbine found.
+ */
+ @Nonnull
+ public static final ShutDownReason NO_TURBINE = SimpleShutDownReason.ofNormal("no_turbine");
+ /**
+ * No correct machine part in controller slot.
+ */
+ @Nonnull
+ public static final ShutDownReason NO_MACHINE_PART = SimpleShutDownReason.ofNormal("no_machine_part");
+ /**
+ * Default unknown state.
+ */
+ @Nonnull
+ public static final ShutDownReason NONE = SimpleShutDownReason.ofNormal("none");
+ /**
+ * Critical unknown state.
+ */
+ @Nonnull
+ public static final ShutDownReason CRITICAL_NONE = SimpleShutDownReason.ofCritical("none");
+
+ /**
+ * Fluid that needs to be constantly supplied are out. E.g. PCB coolant with cooling upgrades enabled.
+ */
+ @Nonnull
+ public static ShutDownReason outOfFluid(@Nonnull FluidStack required) {
+ return new ReasonOutOfFluid(required);
+ }
+
+ /**
+ * Item that needs to be constantly supplied are out.
+ */
+ @Nonnull
+ public static ShutDownReason outOfItem(@Nonnull ItemStack required) {
+ return new ReasonOutOfItem(required);
+ }
+
+ /**
+ * Stuff that needs to be constantly supplied are out.
+ */
+ @Nonnull
+ public static ShutDownReason outOfStuff(@Nonnull String required, int amount) {
+ return new ReasonOutOfStuff(required, amount);
+ }
+
+ static {
+ register(new SimpleShutDownReason("", false));
+ register(new ReasonOutOfFluid(getWater(0)));
+ register(new ReasonOutOfItem(new ItemStack(Items.feather, 1)));
+ register(new ReasonOutOfStuff("stuff", 1));
+ }
+}
diff --git a/src/main/java/gregtech/api/util/shutdown/SimpleShutDownReason.java b/src/main/java/gregtech/api/util/shutdown/SimpleShutDownReason.java
new file mode 100644
index 0000000000..92763fa431
--- /dev/null
+++ b/src/main/java/gregtech/api/util/shutdown/SimpleShutDownReason.java
@@ -0,0 +1,79 @@
+package gregtech.api.util.shutdown;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+
+/**
+ * Simple implementation of {@link ShutDownReason}. You can create new object without registering it.
+ */
+public class SimpleShutDownReason implements ShutDownReason {
+
+ private String key;
+ private boolean wasCritical;
+
+ public SimpleShutDownReason(String key, boolean isCritical) {
+ this.key = key;
+ this.wasCritical = isCritical;
+ }
+
+ @NotNull
+ @Override
+ public String getID() {
+ return "simple_result";
+ }
+
+ @NotNull
+ @Override
+ public String getDisplayString() {
+ return Objects.requireNonNull(StatCollector.translateToLocal("GT5U.gui.text." + key));
+ }
+
+ @NotNull
+ @Override
+ public ShutDownReason newInstance() {
+ return new SimpleShutDownReason("", false);
+ }
+
+ @Override
+ public void encode(@NotNull PacketBuffer buffer) {
+ buffer.writeBoolean(wasCritical);
+ NetworkUtils.writeStringSafe(buffer, key);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ wasCritical = buffer.readBoolean();
+ key = NetworkUtils.readStringSafe(buffer);
+ }
+
+ @Override
+ public boolean wasCritical() {
+ return wasCritical;
+ }
+
+ /**
+ * Creates new reason with critical state. Add your localized description with `GT5U.gui.text.{key}`.
+ * This is already registered to registry.
+ */
+ @Nonnull
+ public static ShutDownReason ofCritical(String key) {
+ return new SimpleShutDownReason(key, true);
+ }
+
+ /**
+ * Creates new reason with normal state. Add your localized description with `GT5U.gui.text.{key}`.
+ * This is already registered to registry.
+ */
+ @Nonnull
+ public static ShutDownReason ofNormal(String key) {
+ return new SimpleShutDownReason(key, false);
+ }
+}