diff --git a/src/main/java/com/newmaa/othtech/Config.java b/src/main/java/com/newmaa/othtech/Config.java index a07a9e98..21548c51 100644 --- a/src/main/java/com/newmaa/othtech/Config.java +++ b/src/main/java/com/newmaa/othtech/Config.java @@ -11,29 +11,55 @@ public class Config { public static void synchronizeConfiguration(File configFile) { Configuration configuration = new Configuration(configFile); - // TODO NEED ENGLISH TRANSLATION O.O // greeting = configuration.getString("greeting", Configuration.CATEGORY_GENERAL, greeting, "How shall I // greet?"); - is_TT_Boom = configuration.getBoolean("OTHTechnology : 控制TT模版机器爆炸", "憋憋", is_TT_Boom, "憋憋"); - NEIFrontend = configuration - .getBoolean("OTHTechnology : 123机器配方池界面使用铱锇钐合金粉替换GT齿轮, true为是, false为替换成憋憋", "A", NEIFrontend, "A"); + is_TT_Boom = configuration.getBoolean( + "OTHTechnology : Control TT Machine Explosion | 控制TT模版机器爆炸", + "Machine Settings", + is_TT_Boom, + "Enable/disable TT template machine explosions | 憋憋"); + NEIFrontend = configuration.getBoolean( + "OTHTechnology : Use Iridium-Osmium-Samarium Powder in Recipe GUI | 123机器配方池界面使用铱锇钐合金粉替换GT齿轮, true为是, false为替换成憋憋", + "UI Settings", + NEIFrontend, + "true: use Ir-Os-Sm powder instead of GT gears, false: use alternative | true为是, false为替换成憋憋"); is_MISA_IMBA_Recipes_Enabled = configuration.getBoolean( - "OTHTechnology : 艾萨集成工厂超模配方是否开启(e.g. 无尽催化剂矿出无尽粉 黑钚矿出黑中子粉), true为是, false为否", - "A", + "OTHTechnology : Enable MISA Overpowered Recipes | 艾萨集成工厂超模配方是否开启(e.g. 无尽催化剂矿出无尽粉 黑钚矿出黑中子粉), true为是, false为否", + "Recipe Settings", is_MISA_IMBA_Recipes_Enabled, - "A"); + "Enable overpowered recipes in MISA Integrated Factory (e.g. infinite catalyst ore -> infinite dust) | true为是, false为否"); is_EggMachine_Recipes_For_NHU = configuration.getBoolean( - "OTHTechnology : 丰矿的NHU配方兼容从123大龙研机(e.g. 一步到位顶级蛋机 龙蛋馄饨龙蛋远古龙蛋配方), true为是, false为否", - "A", + "OTHTechnology : Enable NHU Recipes for Egg Machine | 丰矿的NHU配方兼容从123大龙研机(e.g. 一步到位顶级蛋机 龙蛋馄饨龙蛋远古龙蛋配方), true为是, false为否", + "Recipe Settings", is_EggMachine_Recipes_For_NHU, - "A"); - ENQING_MULTI = configuration - .getFloat("OTHTechnology : 恩情工厂配方产物倍率(float) , 倍率四舍五入", "不憋憋", 1.5f, 1.0f, 114514f, "不憋憋"); - tier_Antimonia = configuration.getInt("OTHTechnology : 锑星登陆需求等级(Tier)", "不憋憋", 4, 1, 10, "笑笑"); - tier_Ross123b = configuration.getInt("OTHTechnology : 锑罗斯登陆需求等级(Tier)", "不憋憋", 1, 1, 10, "笑笑"); - is_Enqing_Song_Play = configuration - .getBoolean("OTHTechnology : 开启将军工厂的开机音效, true为是, false为否", "A", is_Enqing_Song_Play, "A"); + "Enable NHU recipes compatibility (e.g. one-step dragon egg recipes) | true为是, false为否"); + ENQING_MULTI = configuration.getFloat( + "OTHTechnology : Enqing Factory Output Multiplier (float, rounded) | 恩情工厂配方产物倍率(float) , 倍率四舍五入", + "Multipliers", + 1.5f, + 1.0f, + 114514f, + "Output multiplier for Enqing Factory recipes (rounded to nearest integer) | 倍率四舍五入"); + tier_Antimonia = configuration.getInt( + "OTHTechnology : Antimonia Planet Landing Tier Requirement | 锑星登陆需求等级(Tier)", + "Dimension Settings", + 4, + 1, + 10, + "Required tier to land on Antimonia planet | 笑笑"); + tier_Ross123b = configuration.getInt( + "OTHTechnology : Ross123b Planet Landing Tier Requirement | 锑罗斯登陆需求等级(Tier)", + "Dimension Settings", + 1, + 1, + 10, + "Required tier to land on Ross123b planet | 笑笑"); + is_Enqing_Song_Play = configuration.getBoolean( + "OTHTechnology : Enable General Factory Startup Sound | 开启将军工厂的开机音效, true为是, false为否", + "Audio Settings", + is_Enqing_Song_Play, + "Enable/disable General Factory startup sound effect | true为是, false为否"); if (configuration.hasChanged()) { configuration.save(); } diff --git a/src/main/java/com/newmaa/othtech/common/entity/EntityFakePlayer.java b/src/main/java/com/newmaa/othtech/common/entity/EntityFakePlayer.java index d6b97de6..93230a27 100644 --- a/src/main/java/com/newmaa/othtech/common/entity/EntityFakePlayer.java +++ b/src/main/java/com/newmaa/othtech/common/entity/EntityFakePlayer.java @@ -31,9 +31,7 @@ public EntityFakePlayer(World world) { @Override protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier) { - { - this.dropItem(ItemLoader.itemBrain, 1); - } + this.dropItem(ItemLoader.itemBrain, 1); int extraDrops = this.rand.nextInt(8 + lootingModifier); for (int i = 0; i < extraDrops; ++i) { this.dropItem(ModItems.itemMetaFood, 36); diff --git a/src/main/java/com/newmaa/othtech/common/item/itemsHelper/ItemAdder.java b/src/main/java/com/newmaa/othtech/common/item/itemsHelper/ItemAdder.java index 91c3bd03..11fbec90 100644 --- a/src/main/java/com/newmaa/othtech/common/item/itemsHelper/ItemAdder.java +++ b/src/main/java/com/newmaa/othtech/common/item/itemsHelper/ItemAdder.java @@ -1,11 +1,13 @@ package com.newmaa.othtech.common.item.itemsHelper; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; @@ -26,16 +28,12 @@ */ public class ItemAdder extends ItemAdder_Basic { - /** - * An Item Map for managing basic items - */ - // public static Map Item01Map = new HashMap<>(); - /** * A Set contains the meta value that has been used. + * Thread-safe to prevent race conditions during concurrent access. */ - public static final Set MetaSet = new HashSet<>(); - public static final Map MetaItemTooltipsMap = new HashMap<>(); + public static final Set MetaSet = Collections.synchronizedSet(new HashSet<>()); + public static final Map MetaItemTooltipsMap = new ConcurrentHashMap<>(); public final String unlocalizedName; @@ -71,15 +69,6 @@ public static ItemStack initItem(String aName, int aMeta, String[] tooltips) { } - /** - * Init the basic items at the game pre init. - */ - // public static void init() { - // for (String MetaName : Item01Map.keySet()) { - // GameRegistry.registerItem(Item01Map.get(MetaName), MetaName); - // } - // } - // region Overrides @Override diff --git a/src/main/java/com/newmaa/othtech/machine/OTELargeBin.java b/src/main/java/com/newmaa/othtech/machine/OTELargeBin.java index 88790b00..b92ddaae 100644 --- a/src/main/java/com/newmaa/othtech/machine/OTELargeBin.java +++ b/src/main/java/com/newmaa/othtech/machine/OTELargeBin.java @@ -88,11 +88,19 @@ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack a if (Tier >= 5) { Tier = 0; } - return Tier == 1 ? checkPiece(Tier1, 2, 3, 1) - : Tier == 2 ? checkPiece(Tier2, 4, 9, 2) - : Tier == 3 ? checkPiece(Tier3, 7, 18, 3) - : Tier == 4 ? checkPiece(Tier4, 9, 27, 1) : checkPiece(Tier1, 2, 3, 1); - + + switch (Tier) { + case 1: + return checkPiece(Tier1, 2, 3, 1); + case 2: + return checkPiece(Tier2, 4, 9, 2); + case 3: + return checkPiece(Tier3, 7, 18, 3); + case 4: + return checkPiece(Tier4, 9, 27, 1); + default: + return checkPiece(Tier1, 2, 3, 1); + } } @Override @@ -116,12 +124,19 @@ public void construct(ItemStack stackSize, boolean hintsOnly) { public int survivalConstruct(ItemStack stackSize, int elementBudget, IItemSource source, EntityPlayerMP actor) { if (mMachine) return -1; Tier = stackSize.stackSize; - return Tier == 1 ? survivalBuildPiece(Tier1, stackSize, 2, 3, 1, elementBudget, source, actor, false, true) - : Tier == 2 ? survivalBuildPiece(Tier2, stackSize, 4, 9, 2, elementBudget, source, actor, false, true) - : Tier == 3 ? survivalBuildPiece(Tier3, stackSize, 7, 18, 3, elementBudget, source, actor, false, true) - : Tier == 4 - ? survivalBuildPiece(Tier4, stackSize, 9, 27, 1, elementBudget, source, actor, false, true) - : survivalBuildPiece(Tier1, stackSize, 2, 3, 1, elementBudget, source, actor, false, true); + + switch (Tier) { + case 1: + return survivalBuildPiece(Tier1, stackSize, 2, 3, 1, elementBudget, source, actor, false, true); + case 2: + return survivalBuildPiece(Tier2, stackSize, 4, 9, 2, elementBudget, source, actor, false, true); + case 3: + return survivalBuildPiece(Tier3, stackSize, 7, 18, 3, elementBudget, source, actor, false, true); + case 4: + return survivalBuildPiece(Tier4, stackSize, 9, 27, 1, elementBudget, source, actor, false, true); + default: + return survivalBuildPiece(Tier1, stackSize, 2, 3, 1, elementBudget, source, actor, false, true); + } } @Override @@ -566,14 +581,16 @@ public CheckRecipeResult checkProcessing() { if (mode == 0) { mEUt = 0; mMaxProgresstime = getBaseProgressingTick(); - ItemStack[] itemStack = getStoredInputsNoSeparation().toArray(new ItemStack[0]); - FluidStack[] fluidStack = getStoredFluids().toArray(new FluidStack[0]); - if (getStoredInputsNoSeparation() != null) { + Collection storedInputs = getStoredInputsNoSeparation(); + if (storedInputs != null) { + ItemStack[] itemStack = storedInputs.toArray(new ItemStack[0]); for (ItemStack item : itemStack) { item.stackSize -= item.stackSize; } } - if (getStoredFluids() != null) { + Collection storedFluids = getStoredFluids(); + if (storedFluids != null) { + FluidStack[] fluidStack = storedFluids.toArray(new FluidStack[0]); for (FluidStack fluid : fluidStack) { fluid.amount -= fluid.amount; } @@ -582,32 +599,37 @@ public CheckRecipeResult checkProcessing() { } else if (mode == 1) { mMaxProgresstime = getBaseProgressingTick(); int a; - ItemStack[] itemStack = getStoredInputsNoSeparation().toArray(new ItemStack[0]); - for (ItemStack item : itemStack) { - if (item.stackSize <= getMaxParallelRecipes()) { - a = item.stackSize; - mEUt = (30 * a); - item.stackSize -= item.stackSize; - mOutputItems = new ItemStack[] { - setStackSize(ItemList.IC2_Scrap.get(1), (int) Math.floor(a * 0.5)) }; - } else { - a = getMaxParallelRecipes(); - mEUt = (30 * a); - item.stackSize -= getMaxParallelRecipes(); - mOutputItems = new ItemStack[] { - setStackSize(ItemList.IC2_Scrap.get(1), (int) Math.floor(a * 0.5)) }; + Collection storedInputs = getStoredInputsNoSeparation(); + if (storedInputs != null) { + ItemStack[] itemStack = storedInputs.toArray(new ItemStack[0]); + for (ItemStack item : itemStack) { + if (item.stackSize <= getMaxParallelRecipes()) { + a = item.stackSize; + mEUt = (30 * a); + item.stackSize -= item.stackSize; + mOutputItems = new ItemStack[] { + setStackSize(ItemList.IC2_Scrap.get(1), (int) Math.floor(a * 0.5)) }; + } else { + a = getMaxParallelRecipes(); + mEUt = (30 * a); + item.stackSize -= getMaxParallelRecipes(); + mOutputItems = new ItemStack[] { + setStackSize(ItemList.IC2_Scrap.get(1), (int) Math.floor(a * 0.5)) }; + } } } } else if (mode == 2) { mMaxProgresstime = getBaseProgressingTick(); - ItemStack[] itemStack = getStoredInputsNoSeparation().toArray(new ItemStack[0]); - for (ItemStack item : itemStack) { - if (item.stackSize >= 256000) { - mSA += 256000; - item.stackSize -= 256000; - if (mSA >= 256000) { - mOutputItems = new ItemStack[] { - GTModHandler.getModItem(AppliedEnergistics2.ID, "item.ItemMultiMaterial", 1, 47) }; + Collection storedInputs = getStoredInputsNoSeparation(); + if (storedInputs != null) { + ItemStack[] itemStack = storedInputs.toArray(new ItemStack[0]); + for (ItemStack item : itemStack) { + if (item.stackSize >= 256000) { + mSA += 256000; + item.stackSize -= 256000; + if (mSA >= 256000) { + mOutputItems = new ItemStack[] { + GTModHandler.getModItem(AppliedEnergistics2.ID, "item.ItemMultiMaterial", 1, 47) }; mSA -= 256000; } } else { diff --git a/src/main/java/com/newmaa/othtech/machine/OTEMegaQFT.java b/src/main/java/com/newmaa/othtech/machine/OTEMegaQFT.java index c047969a..4e82279f 100644 --- a/src/main/java/com/newmaa/othtech/machine/OTEMegaQFT.java +++ b/src/main/java/com/newmaa/othtech/machine/OTEMegaQFT.java @@ -68,12 +68,18 @@ public OTEMegaQFT(String aName) { private byte mode = 0; private int multiplier = 1; private String plier = "0"; + + // NBT version for backward compatibility + private static final int NBT_VERSION = 1; + // Maximum time acceleration level (10 = 100% speedup, based on getSpeedBonus formula) + private static final int MAX_TIME_ACCELERATION = 10; @Override public void saveNBTData(NBTTagCompound aNBT) { super.saveNBTData(aNBT); + aNBT.setInteger("nbtVersion", NBT_VERSION); aNBT.setInteger("stabilisationFieldMetadata", stabilisationFieldMetadata); aNBT.setInteger("spacetimeCompressionFieldMetadata", spacetimeCompressionFieldMetadata); aNBT.setInteger("timeAccelerationFieldMetadata", timeAccelerationFieldMetadata); @@ -86,11 +92,18 @@ public void saveNBTData(NBTTagCompound aNBT) { public void loadNBTData(final NBTTagCompound aNBT) { super.loadNBTData(aNBT); - stabilisationFieldMetadata = aNBT.getInteger("stabilisationFieldMetadata"); - spacetimeCompressionFieldMetadata = aNBT.getInteger("spacetimeCompressionFieldMetadata"); - timeAccelerationFieldMetadata = aNBT.getInteger("timeAccelerationFieldMetadata"); + // Check NBT version for compatibility - future versions can add migration logic here + int nbtVersion = aNBT.hasKey("nbtVersion") ? aNBT.getInteger("nbtVersion") : 0; + + // Version 0 (legacy): Load without validation + // Version 1: Load with bounds checking and sanitization + + // Sanitize and validate input values with bounds checking + stabilisationFieldMetadata = Math.max(0, aNBT.getInteger("stabilisationFieldMetadata")); + spacetimeCompressionFieldMetadata = Math.max(0, aNBT.getInteger("spacetimeCompressionFieldMetadata")); + timeAccelerationFieldMetadata = Math.max(0, Math.min(MAX_TIME_ACCELERATION, aNBT.getInteger("timeAccelerationFieldMetadata"))); mode = aNBT.getByte("mode"); - multiplier = aNBT.getInteger("multiplier"); + multiplier = Math.max(1, aNBT.getInteger("multiplier")); } diff --git a/src/main/java/com/newmaa/othtech/machine/hatch/OTEHatchRack.java b/src/main/java/com/newmaa/othtech/machine/hatch/OTEHatchRack.java index 7ba24c09..1e4c19f4 100644 --- a/src/main/java/com/newmaa/othtech/machine/hatch/OTEHatchRack.java +++ b/src/main/java/com/newmaa/othtech/machine/hatch/OTEHatchRack.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.player.EntityPlayer; @@ -56,7 +57,8 @@ public class OTEHatchRack extends MTEHatch implements IAddGregtechLogo, IAddUIWi private static Textures.BlockIcons.CustomIcon EM_R; private static Textures.BlockIcons.CustomIcon EM_R_ACTIVE; private float overClock = 1, overVolt = 1; - private static final Map componentBinds = new HashMap<>(); + // Thread-safe map to prevent race conditions during concurrent access + private static final Map componentBinds = new ConcurrentHashMap<>(); private String clientLocale = "en_US"; diff --git a/src/main/java/com/newmaa/othtech/recipe/RecipeLoader.java b/src/main/java/com/newmaa/othtech/recipe/RecipeLoader.java index 7b944a67..231ba714 100644 --- a/src/main/java/com/newmaa/othtech/recipe/RecipeLoader.java +++ b/src/main/java/com/newmaa/othtech/recipe/RecipeLoader.java @@ -2,6 +2,9 @@ import static com.newmaa.othtech.Config.is_EggMachine_Recipes_For_NHU; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import net.minecraftforge.fluids.FluidRegistry; import com.newmaa.othtech.machine.OTEMiniSteamNineInOne; @@ -15,6 +18,8 @@ public class RecipeLoader { + private static final Logger LOG = LogManager.getLogger(RecipeLoader.class); + public static void loadRecipes() { IRecipePool[] recipePools = new IRecipePool[] { new RecipesComponentAssemblyLineRecipes(), new RecipesBlastFurnaceRecipes(), new RecipesFreezerRecipes(), new RecipesMain(), new RecipesMAXs(), @@ -23,31 +28,55 @@ public static void loadRecipes() { new RecipesTangshanSteelFactory(), new RecipesSunFactoryEnqing(), new RecipesEpicCokeOvenFake(), new RecipesWoodenFusionReactor(), new RecipesMISA(), new RecipesNaquadah(), new RecipesEIO(), new RecipesEXH(), new RecipesNewWetware(), new RecipesAntimonia(), new RecipesNASA() }; - OTEMiniSteamNineInOne.loadRecipes(); + + try { + OTEMiniSteamNineInOne.loadRecipes(); + } catch (Exception e) { + LOG.error("Failed to load OTEMiniSteamNineInOne recipes", e); + } + if (!modsEnum.TwistSpaceTechnology.isModLoaded()) { - new RecipesCopiedFromTST().loadRecipes(); + try { + new RecipesCopiedFromTST().loadRecipes(); + } catch (Exception e) { + LOG.error("Failed to load RecipesCopiedFromTST recipes", e); + } } + if (modsEnum.NHUtilities.isModLoaded() && is_EggMachine_Recipes_For_NHU) { - new RecipesDE().loadRecipes(); + try { + new RecipesDE().loadRecipes(); + } catch (Exception e) { + LOG.error("Failed to load RecipesDE recipes", e); + } } + if (!modsEnum.GTNN.isModLoaded()) { - // 78water - GTValues.RA.stdBuilder() - .itemOutputs(GTModHandler.getModItem("miscutils", "item.BasicGenericChemItem", 1, 30)) - .fluidInputs(FluidRegistry.getFluidStack("molten.shirabon", 92160)) - .itemInputs( - GTUtility.getIntegratedCircuit(10), - GTModHandler.getModItem("miscutils", "item.BasicAgrichemItem", 1, 13), - GTModHandler.getModItem("bartworks", "gt.bwMetaGeneratedlens", 64, 25), - GTModHandler.getModItem("gregtech", "gt.metaitem.03", 64, 4054), - GTModHandler.getModItem("gregtech", "gt.metaitem.03", 64, 32722)) - .duration(60 * 20) - .eut(TierEU.UMV) - .addTo(RecipeMaps.assemblerRecipes); - + try { + // 78water + GTValues.RA.stdBuilder() + .itemOutputs(GTModHandler.getModItem("miscutils", "item.BasicGenericChemItem", 1, 30)) + .fluidInputs(FluidRegistry.getFluidStack("molten.shirabon", 92160)) + .itemInputs( + GTUtility.getIntegratedCircuit(10), + GTModHandler.getModItem("miscutils", "item.BasicAgrichemItem", 1, 13), + GTModHandler.getModItem("bartworks", "gt.bwMetaGeneratedlens", 64, 25), + GTModHandler.getModItem("gregtech", "gt.metaitem.03", 64, 4054), + GTModHandler.getModItem("gregtech", "gt.metaitem.03", 64, 32722)) + .duration(60 * 20) + .eut(TierEU.UMV) + .addTo(RecipeMaps.assemblerRecipes); + } catch (Exception e) { + LOG.error("Failed to load GTNN custom recipe", e); + } } + for (IRecipePool recipePool : recipePools) { - recipePool.loadRecipes(); + try { + recipePool.loadRecipes(); + } catch (Exception e) { + LOG.error("Failed to load recipes from pool: " + recipePool.getClass().getSimpleName(), e); + } } } diff --git a/src/main/java/com/newmaa/othtech/utils/RecipeBuilder.java b/src/main/java/com/newmaa/othtech/utils/RecipeBuilder.java index 8c1e1b8f..74f900d8 100644 --- a/src/main/java/com/newmaa/othtech/utils/RecipeBuilder.java +++ b/src/main/java/com/newmaa/othtech/utils/RecipeBuilder.java @@ -68,7 +68,12 @@ public RecipeBuilder eut(int eut) { } public RecipeBuilder eut(long eut) { - this.eut = (int) eut; + // Safe conversion with overflow check - clamp to int range + if (eut > Integer.MAX_VALUE) { + this.eut = Integer.MAX_VALUE; + } else { + this.eut = (int) eut; + } return this; } diff --git a/src/main/java/com/newmaa/othtech/utils/TextHandler.java b/src/main/java/com/newmaa/othtech/utils/TextHandler.java index 8fc674ec..6265e1eb 100644 --- a/src/main/java/com/newmaa/othtech/utils/TextHandler.java +++ b/src/main/java/com/newmaa/othtech/utils/TextHandler.java @@ -13,12 +13,15 @@ public class TextHandler { public static Map LangMapNeedToWrite = new HashMap<>(); public static String texter(String aTextLine, String aKey) { + if (aTextLine == null || aKey == null) { + return "texterError: null input"; + } /** * If not in Dev mode , return vanilla forge method directly. */ if (OTHTechnology.isInDevMode) { - if (LangMap.get(aKey) == null) { + if (LangMap == null || LangMap.get(aKey) == null) { OTHTechnology.LOG.info("Texter get a new key - TextLine: " + aKey + " - " + aTextLine); LangMapNeedToWrite.put(aKey, aTextLine); return aTextLine; @@ -32,8 +35,11 @@ public static String texter(String aTextLine, String aKey) { } public static String texterButKey(String aTextLine, String aKey) { + if (aTextLine == null || aKey == null) { + return "texterError: null input"; + } if (OTHTechnology.isInDevMode) { - if (LangMap.get(aKey) == null) { + if (LangMap == null || LangMap.get(aKey) == null) { OTHTechnology.LOG.info("Texter get a new key - TextLine: " + aKey + " - " + aTextLine); LangMapNeedToWrite.put(aKey, aTextLine); } @@ -46,9 +52,12 @@ public static String texterButKey(String aTextLine, String aKey) { * {@link TextHandler#texter(String aTextLine, String aKey)} * * @param aTextLine The default String to where you use. - * @return + * @return The localized text or error message */ public static String texter(String aTextLine) { + if (aTextLine == null) { + return "texterError: null input"; + } String aKey = "Auto." + aTextLine + ".text"; return texter(aTextLine, aKey); } diff --git a/src/main/java/com/newmaa/othtech/utils/Utils.java b/src/main/java/com/newmaa/othtech/utils/Utils.java index 33c6c717..7d83f0c2 100644 --- a/src/main/java/com/newmaa/othtech/utils/Utils.java +++ b/src/main/java/com/newmaa/othtech/utils/Utils.java @@ -51,6 +51,12 @@ public static int multiBuildPiece(int... buildPieces) { } public static ItemStack addStringToStackName(ItemStack itemStack, String extra) { + if (itemStack == null) { + return null; + } + if (extra == null || extra.isEmpty()) { + return itemStack; + } String originName = itemStack.getDisplayName(); String newName = originName + " " + extra;