diff --git a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java
index 0f302371..6ca0a358 100644
--- a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java
+++ b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java
@@ -1,21 +1,22 @@
package goodgenerator.blocks.tileEntity.GTMetaTileEntity;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
-import com.gtnewhorizons.modularui.api.drawable.Text;
import com.gtnewhorizons.modularui.api.math.Alignment;
import com.gtnewhorizons.modularui.api.math.Color;
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
import com.gtnewhorizons.modularui.common.widget.TextWidget;
-import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
-import goodgenerator.blocks.tileEntity.NeutronActivator;
-import goodgenerator.util.CharExchanger;
+import crazypants.enderio.Log;
import gregtech.api.enums.Textures;
import gregtech.api.gui.modularui.GT_UIInfos;
import gregtech.api.gui.modularui.GT_UITextures;
@@ -25,6 +26,8 @@
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.gui.modularui.widget.CoverCycleButtonWidget;
public class NeutronSensor extends GT_MetaTileEntity_Hatch {
@@ -32,7 +35,8 @@ public class NeutronSensor extends GT_MetaTileEntity_Hatch {
private static final IIconContainer textureFont_Glow = new Textures.BlockIcons.CustomIcon(
"icons/NeutronSensorFont_GLOW");
- protected String texts = "";
+ protected int threshold = 0;
+ protected boolean inverted = false;
boolean isOn = false;
public NeutronSensor(int aID, String aName, String aNameRegional, int aTier) {
@@ -52,13 +56,91 @@ public String[] getDescription() {
@Override
public void loadNBTData(NBTTagCompound aNBT) {
- texts = aNBT.getString("mBoxContext");
+ if (aNBT.hasKey("mBoxContext")) {
+ // Convert legacy settings
+ setThresholdFromString(aNBT.getString("mBoxContext"));
+ } else {
+ threshold = aNBT.getInteger("mThreshold");
+ inverted = aNBT.getBoolean("mInverted");
+ }
super.loadNBTData(aNBT);
}
+ /**
+ * Used to convert legacy setting where the sensor would use a string like ">200keV" to set its threshold. This
+ * method updates the {@link #threshold} and {@link #inverted} fields based on the input string. The string is
+ * assumed to be in format "(operator)(value)[suffix](ev)", where:
+ *
+ * - (operator) is one of "<", ">", "<=", ">=", "==", or "!="
+ * - (value) is a numeric value (sequence of decimal digits)
+ * - (suffix) is "k", "K", "m", or "M" (optional)
+ * - (ev) is the string "ev", case-insensitive.
+ *
+ * Note that operators "==" and "!=" can not be converted exactly, as the new threshold supports only a binary
+ * comparison (less than, or greater than or equal). Thus "==" is interpreted in the same way as "<=", and "!=" as
+ * ">". This shouldn't be a big problem for real setups, because one should probably not be testing for strict
+ * equality here anyway. The possible reasonable conditions "==0eV" and "!=0eV" will continue working as before.
+ *
+ * @param text String to convert.
+ */
+ private void setThresholdFromString(String text) {
+ Matcher matcher = Pattern.compile("^(<|>|<=|>=|==|!=)([0-9]*)(|k|m)(ev)$", Pattern.CASE_INSENSITIVE)
+ .matcher(text);
+
+ if (!matcher.matches()) {
+ Log.error("Failed to parse Neutron Sensor setting: \"" + text + "\"!");
+ return;
+ }
+
+ String operator = matcher.group(1);
+ String value = matcher.group(2);
+ String suffix = matcher.group(3);
+
+ int newThreshold = Integer.parseInt(value);
+
+ switch (suffix) {
+ case "k":
+ case "K":
+ newThreshold *= 1000;
+ break;
+ case "m":
+ case "M":
+ newThreshold *= 1_000_000;
+ break;
+ }
+
+ switch (operator) {
+ case "<":
+ threshold = newThreshold;
+ inverted = true;
+ break;
+ case ">":
+ threshold = newThreshold + 1;
+ inverted = false;
+ break;
+ case "<=":
+ threshold = newThreshold + 1;
+ inverted = true;
+ break;
+ case ">=":
+ threshold = newThreshold;
+ inverted = false;
+ break;
+ case "==": // Interpret as <= to keep "==0eV" working as before.
+ threshold = newThreshold + 1;
+ inverted = true;
+ break;
+ case "!=": // Interpret as > to keep "!=0eV" working as before.
+ threshold = newThreshold + 1;
+ inverted = false;
+ break;
+ }
+ }
+
@Override
public void saveNBTData(NBTTagCompound aNBT) {
- aNBT.setString("mBoxContext", texts);
+ aNBT.setInteger("mThreshold", threshold);
+ aNBT.setBoolean("mInverted", inverted);
super.saveNBTData(aNBT);
}
@@ -94,20 +176,13 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye
return true;
}
- public void setText(String text) {
- texts = text == null ? "" : text;
- }
-
- public String getText() {
- return texts == null ? "" : texts;
- }
-
- public void outputRedstoneSignal() {
- isOn = true;
- }
-
- public void stopOutputRedstoneSignal() {
- isOn = false;
+ /**
+ * Updates redstone output strength based on the eV of the multiblock.
+ *
+ * @param eV Amount of eV to compare.
+ */
+ public void updateRedstoneOutput(int eV) {
+ isOn = (eV >= threshold) ^ inverted;
}
@Override
@@ -164,50 +239,29 @@ public boolean useModularUI() {
@Override
public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
- TextFieldWidget textField = new TextFieldWidget();
+ final String INVERTED = GT_Utility.trans("INVERTED", "Inverted");
+ final String NORMAL = GT_Utility.trans("NORMAL", "Normal");
+
builder.widget(
- textField.setGetter(this::getText).setSetter(this::setText)
- .setValidator(
- str -> isValidExpression(str) ? str
- : textField.getLastText().size() > 0 ? textField.getLastText().get(0) : "")
- .setFocusOnGuiOpen(true).setTextColor(Color.WHITE.dark(1))
- .setTextAlignment(Alignment.CenterLeft)
- .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2)).setPos(8, 48)
- .setSize(100, 18))
+ new CoverCycleButtonWidget().setToggle(() -> inverted, (val) -> inverted = val)
+ .setTextureGetter(
+ (state) -> state == 1 ? GT_UITextures.OVERLAY_BUTTON_REDSTONE_ON
+ : GT_UITextures.OVERLAY_BUTTON_REDSTONE_OFF)
+ .addTooltip(0, NORMAL).addTooltip(1, INVERTED).setPos(10, 8))
.widget(
- new TextWidget(StatCollector.translateToLocal("gui.NeutronSensor.0"))
+ new TextWidget().setStringSupplier(() -> inverted ? INVERTED : NORMAL)
.setDefaultColor(COLOR_TEXT_GRAY.get()).setTextAlignment(Alignment.CenterLeft)
- .setPos(8, 8))
+ .setPos(28, 12))
.widget(
- new TextWidget(StatCollector.translateToLocal("gui.NeutronSensor.1"))
- .setDefaultColor(COLOR_TEXT_GRAY.get()).setPos(8, 32))
+ new NumericWidget().setBounds(0, 1200000000).setGetter(() -> threshold)
+ .setSetter((value) -> threshold = (int) value).setScrollValues(1000, 1, 1_000_000)
+ .setTextColor(Color.WHITE.dark(1)).setTextAlignment(Alignment.CenterLeft)
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2))
+ .setPos(10, 28).setSize(77, 12))
.widget(
- TextWidget.dynamicText(
- () -> isValidExpression(textField.getText())
- ? new Text(StatCollector.translateToLocal("gui.NeutronSensor.2"))
- .color(0x077d02)
- : new Text(StatCollector.translateToLocal("gui.NeutronSensor.3"))
- .color(COLOR_TEXT_RED.get()))
- .setSynced(false).setPos(120, 53));
- }
-
- private boolean isValidExpression(String exp) {
- return isValidSuffix(exp) && CharExchanger.isValidCompareExpress(NeutronActivator.rawProcessExp(exp));
- }
-
- private boolean isValidSuffix(String exp) {
- int index;
- index = exp.length() - 1;
- if (index < 0) return false;
- if (exp.charAt(index) != 'V' && exp.charAt(index) != 'v') return false;
- index = exp.length() - 2;
- if (index < 0) return false;
- if (exp.charAt(index) != 'E' && exp.charAt(index) != 'e') return false;
- index = exp.length() - 3;
- if (index < 0) return false;
- return exp.charAt(index) == 'M' || exp.charAt(index) == 'm'
- || exp.charAt(index) == 'K'
- || exp.charAt(index) == 'k'
- || Character.isDigit(exp.charAt(index));
+ new TextWidget(StatCollector.translateToLocal("gui.NeutronSensor.4"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get()).setTextAlignment(Alignment.CenterLeft)
+ .setPos(90, 30));
}
}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java b/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java
index 21b1ec38..3b77aaf6 100644
--- a/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java
+++ b/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java
@@ -24,6 +24,7 @@
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
import com.gtnewhorizons.modularui.common.widget.SlotWidget;
@@ -34,7 +35,6 @@
import goodgenerator.blocks.tileEntity.GTMetaTileEntity.NeutronSensor;
import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
import goodgenerator.loader.Loaders;
-import goodgenerator.util.CharExchanger;
import goodgenerator.util.DescTextLocalization;
import goodgenerator.util.ItemRefer;
import gregtech.api.GregTech_API;
@@ -69,6 +69,7 @@ public class NeutronActivator extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
protected int height = 0;
protected int eV = 0, mCeil = 0, mFloor = 0;
private GT_Recipe lastRecipe;
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
final XSTR R = new XSTR();
private static final IIconContainer textureFontOn = new Textures.BlockIcons.CustomIcon("icons/NeutronActivator_On");
@@ -346,12 +347,7 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
if (this.eV > maxNeutronKineticEnergy()) doExplosion(4 * 32);
for (NeutronSensor tHatch : mNeutronSensor) {
- String tText = tHatch.getText();
- if (CharExchanger.isValidCompareExpress(rawProcessExp(tText))) {
- if (CharExchanger.compareExpression(rawProcessExp(tText), eV)) {
- tHatch.outputRedstoneSignal();
- } else tHatch.stopOutputRedstoneSignal();
- }
+ tHatch.updateRedstoneOutput(this.eV);
}
if (mProgresstime < mMaxProgresstime && (eV > mCeil || eV < mFloor)) {
@@ -362,26 +358,6 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
}
}
- public static String rawProcessExp(String exp) {
- StringBuilder ret = new StringBuilder();
- for (char c : exp.toCharArray()) {
- if (exp.length() - ret.length() == 3) {
- if (Character.isDigit(c)) ret.append(c);
- else {
- if (c == 'K' || c == 'k') {
- ret.append("000");
- }
- if (c == 'M' || c == 'm') {
- ret.append("000000");
- }
- }
- break;
- }
- ret.append(c);
- }
- return ret.toString();
- }
-
@Override
public void construct(ItemStack stackSize, boolean hintsOnly) {
structureBuild_EM(NA_BOTTOM, 2, 0, 0, stackSize, hintsOnly);
@@ -470,25 +446,12 @@ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inve
new TextWidget(StatCollector.translateToLocal("gui.NeutronActivator.0"))
.setDefaultColor(COLOR_TEXT_WHITE.get()))
.widget(
- TextWidget.dynamicString(() -> processNumber(eV) + "eV").setSynced(false)
+ new TextWidget().setStringSupplier(() -> numberFormat.formatWithSuffix(eV) + "eV")
.setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.IntegerSyncer(() -> eV, val -> eV = val));
}
- private String processNumber(int num) {
- float num2;
- num2 = ((float) num) / 1000F;
- if (num2 <= 0) {
- return String.format("%d", num);
- }
- if (num2 < 1000.0) {
- return String.format("%.1fK", num2);
- }
- num2 /= 1000F;
- return String.format("%.1fM", num2);
- }
-
private enum NeutronHatchElement implements IHatchElement {
NeutronSensor(NeutronActivator::addAcceleratorAndSensor, NeutronSensor.class) {
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java b/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java
index b16b3613..4e1d0c0f 100644
--- a/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java
+++ b/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java
@@ -31,6 +31,7 @@
import com.gtnewhorizon.structurelib.structure.IStructureElement;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
import com.gtnewhorizons.modularui.api.drawable.IDrawable;
import com.gtnewhorizons.modularui.api.drawable.UITexture;
import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
@@ -82,6 +83,7 @@ public class YottaFluidTank extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
protected final String YOTTANK_BOTTOM = mName + "buttom";
protected final String YOTTANK_MID = mName + "mid";
protected final String YOTTANK_TOP = mName + "top";
+ protected final NumberFormatMUI numberFormat = new NumberFormatMUI();
protected boolean voidExcessEnabled = false;
@@ -523,34 +525,34 @@ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inve
screenElements
.widget(
- TextWidget
- .dynamicString(
+ new TextWidget()
+ .setStringSupplier(
() -> StatCollector.translateToLocal("gui.YOTTank.0") + " "
- + CharExchanger.formatNumber(mStorage.toString())
+ + numberFormat.format(mStorage)
+ " L")
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.BigIntegerSyncer(() -> mStorage, val -> mStorage = val))
.widget(
- TextWidget
- .dynamicString(
+ new TextWidget()
+ .setStringSupplier(
() -> StatCollector.translateToLocal("gui.YOTTank.1") + " " + getFluidName())
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.StringSyncer(() -> mFluidName, val -> mFluidName = val))
.widget(
- TextWidget
- .dynamicString(
+ new TextWidget()
+ .setStringSupplier(
() -> StatCollector.translateToLocal("gui.YOTTank.2") + " "
- + CharExchanger.formatNumber(mStorageCurrent.toString())
+ + numberFormat.format(mStorageCurrent)
+ " L")
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.BigIntegerSyncer(() -> mStorageCurrent, val -> mStorageCurrent = val))
.widget(
- TextWidget.dynamicString(
+ new TextWidget().setStringSupplier(
() -> StatCollector.translateToLocal("gui.YOTTank.3") + " " + getLockedFluidName())
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.StringSyncer(() -> mLockedFluidName, val -> mLockedFluidName = val))
.widget(new FakeSyncWidget.BooleanSyncer(() -> isFluidLocked, val -> isFluidLocked = val))
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java
index 1792c690..5d903681 100644
--- a/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java
+++ b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java
@@ -29,6 +29,7 @@
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
import com.gtnewhorizons.modularui.common.widget.SlotWidget;
@@ -590,6 +591,7 @@ public String[] getInfoData() {
}
protected long energyStorageCache;
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
@Override
protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
@@ -597,21 +599,21 @@ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inve
screenElements
.widget(
- TextWidget
- .dynamicString(
+ new TextWidget()
+ .setStringSupplier(
() -> StatCollector.translateToLocal("gui.LargeFusion.0") + " "
- + GT_Utility.formatNumbers(energyStorageCache)
+ + numberFormat.format(energyStorageCache)
+ " EU")
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.LongSyncer(this::maxEUStore, val -> energyStorageCache = val))
.widget(
- TextWidget
- .dynamicString(
+ new TextWidget()
+ .setStringSupplier(
() -> StatCollector.translateToLocal("gui.LargeFusion.1") + " "
- + GT_Utility.formatNumbers(getEUVar())
+ + numberFormat.format(getEUVar())
+ " EU")
- .setSynced(false).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
.widget(new FakeSyncWidget.LongSyncer(this::getEUVar, this::setEUVar));
}
diff --git a/src/main/java/goodgenerator/util/CharExchanger.java b/src/main/java/goodgenerator/util/CharExchanger.java
index f080678d..8086fbf6 100644
--- a/src/main/java/goodgenerator/util/CharExchanger.java
+++ b/src/main/java/goodgenerator/util/CharExchanger.java
@@ -20,101 +20,6 @@ public static char shifter(int unicode) {
return (char) unicode;
}
- public static boolean isValidCompareExpressChar(char c) {
- return Character.isDigit(c) || c == '<' || c == '>' || c == '=' || c == '!';
- }
-
- public static boolean isValidCompareExpress(String exp) {
- if (exp.length() < 2) return false;
- for (char c : exp.toCharArray()) if (!isValidCompareExpressChar(c)) return false;
- char c1 = exp.charAt(0), c2 = exp.charAt(1);
- String subExp = "" + c1;
- if (!Character.isDigit(c2)) subExp = subExp + c2;
- switch (subExp) {
- case ">":
- case "<":
- case ">=":
- case "<=":
- case "==":
- case "!=":
- break;
- default:
- return false;
- }
- if (exp.length() == subExp.length()) return false;
- for (int i = subExp.length(); i < exp.length(); i++) {
- if (!Character.isDigit(exp.charAt(i))) return false;
- }
- return true;
- }
-
- /**
- * ">" : 1
- * "<" : 2
- * "==" : 13
- * "!=" : 14
- * ">=" : 11
- * "<=" : 12
- * INVALID : -1
- */
- public static int getOperator(String exp) {
- char c1, c2;
- int ret;
- if (exp.length() < 1) return -1;
- c1 = exp.charAt(0);
- switch (c1) {
- case '>':
- ret = 1;
- break;
- case '<':
- ret = 2;
- break;
- case '=':
- ret = 3;
- break;
- case '!':
- ret = 4;
- break;
- default:
- return -1;
- }
- if (exp.length() > 1) c2 = exp.charAt(1);
- else return ret;
- if (c2 == '=') {
- ret += 10;
- }
- return ret;
- }
-
- public static boolean compareExpression(String exp, int num) {
- int op = getOperator(exp);
- String NumExp = exp;
- String[] opChar = new String[] { ">", "<", "=", "!" };
- if (op == -1) throw new IllegalArgumentException();
- for (String re : opChar) NumExp = NumExp.replace(re, "");
- long num2 = 0;
- for (char c : NumExp.toCharArray()) {
- num2 *= 10;
- num2 += c - '0';
- }
- switch (op) {
- case 1:
- return num > num2;
- case 2:
- return num < num2;
- case 13:
- return num == num2;
- case 14:
- return num != num2;
- case 11:
- return num >= num2;
- case 12:
- return num <= num2;
- default:
- return false;
- }
- }
-
public static String formatNumber(String exp) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < exp.length(); ++i) {
diff --git a/src/main/resources/assets/goodgenerator/lang/en_US.lang b/src/main/resources/assets/goodgenerator/lang/en_US.lang
index 7c579e23..3a5f05ed 100644
--- a/src/main/resources/assets/goodgenerator/lang/en_US.lang
+++ b/src/main/resources/assets/goodgenerator/lang/en_US.lang
@@ -300,6 +300,7 @@ gui.NeutronSensor.0=Input the value of Neutron Kinetic Energy.
gui.NeutronSensor.1=e.g. >5000KeV, <=30MeV . . .
gui.NeutronSensor.2=Valid
gui.NeutronSensor.3=Invalid
+gui.NeutronSensor.4=eV threshold
gui.NeutronActivator.0=Current Neutron Kinetic Energy:
gui.NeutronActivator.1=Input:
gui.YOTTank.0=Capacity: