From 6f31720697bcc351421a4d86ba3bf749375dd12c Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sat, 27 Aug 2022 10:19:57 +0100 Subject: Update buildscript & apply spotless (#1306) * Update dependencies * Update buildscript, apply spotless --- .../gregtech/api/util/ColorsMetadataSection.java | 16 +- .../api/util/ColorsMetadataSectionSerializer.java | 32 +- .../java/gregtech/api/util/GT_ApiaryUpgrade.java | 53 +- .../gregtech/api/util/GT_AssemblyLineUtils.java | 1023 ++--- .../gregtech/api/util/GT_Assemblyline_Server.java | 722 ++-- src/main/java/gregtech/api/util/GT_BaseCrop.java | 145 +- src/main/java/gregtech/api/util/GT_BlockMap.java | 221 +- src/main/java/gregtech/api/util/GT_BlockSet.java | 48 +- src/main/java/gregtech/api/util/GT_CLS_Compat.java | 56 +- .../gregtech/api/util/GT_ChunkAssociatedData.java | 820 ++-- .../gregtech/api/util/GT_CircuitryBehavior.java | 58 +- .../gregtech/api/util/GT_ClientPreference.java | 6 +- src/main/java/gregtech/api/util/GT_Config.java | 30 +- .../java/gregtech/api/util/GT_CoverBehavior.java | 192 +- .../gregtech/api/util/GT_CoverBehaviorBase.java | 196 +- .../api/util/GT_ExoticEnergyInputHelper.java | 110 +- src/main/java/gregtech/api/util/GT_FoodStat.java | 13 +- .../java/gregtech/api/util/GT_Forestry_Compat.java | 129 +- src/main/java/gregtech/api/util/GT_GC_Compat.java | 23 +- .../gregtech/api/util/GT_HatchElementBuilder.java | 158 +- .../api/util/GT_ItsNotMyFaultException.java | 3 +- .../java/gregtech/api/util/GT_LanguageManager.java | 529 +-- src/main/java/gregtech/api/util/GT_Log.java | 4 +- src/main/java/gregtech/api/util/GT_ModHandler.java | 1167 ++++-- .../api/util/GT_Multiblock_Tooltip_Builder.java | 975 ++--- .../gregtech/api/util/GT_OreDictUnificator.java | 164 +- .../java/gregtech/api/util/GT_PlayedSound.java | 9 +- .../api/util/GT_ProcessingArray_Manager.java | 7 +- src/main/java/gregtech/api/util/GT_Recipe.java | 4076 ++++++++++++++++---- .../gregtech/api/util/GT_RecipeRegistrator.java | 513 ++- .../java/gregtech/api/util/GT_RenderingWorld.java | 328 +- .../java/gregtech/api/util/GT_Shaped_Recipe.java | 37 +- .../gregtech/api/util/GT_Shapeless_Recipe.java | 69 +- .../gregtech/api/util/GT_Single_Recipe_Check.java | 28 +- .../GT_Single_Recipe_Check_Processing_Array.java | 31 +- .../gregtech/api/util/GT_SpawnEventHandler.java | 20 +- .../gregtech/api/util/GT_StructureUtility.java | 202 +- .../gregtech/api/util/GT_ToolHarvestHelper.java | 118 +- .../gregtech/api/util/GT_TooltipDataCache.java | 14 +- src/main/java/gregtech/api/util/GT_Util.java | 96 +- src/main/java/gregtech/api/util/GT_Utility.java | 2285 +++++++---- .../java/gregtech/api/util/GT_UtilityClient.java | 68 +- .../java/gregtech/api/util/IGT_HatchAdder.java | 4 +- .../gregtech/api/util/ISerializableObject.java | 15 +- .../java/gregtech/api/util/LightingHelper.java | 1108 ++++-- .../api/util/WorldSpawnedEventBuilder.java | 119 +- .../gregtech/api/util/extensions/IteratorExt.java | 1 - 47 files changed, 10868 insertions(+), 5173 deletions(-) (limited to 'src/main/java/gregtech/api/util') diff --git a/src/main/java/gregtech/api/util/ColorsMetadataSection.java b/src/main/java/gregtech/api/util/ColorsMetadataSection.java index 2851435061..9f1c4f3ffe 100644 --- a/src/main/java/gregtech/api/util/ColorsMetadataSection.java +++ b/src/main/java/gregtech/api/util/ColorsMetadataSection.java @@ -2,10 +2,8 @@ package gregtech.api.util; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import java.util.Map; import java.util.HashMap; -import gregtech.api.util.GT_Log; -import gregtech.api.GregTech_API; +import java.util.Map; import net.minecraft.client.resources.data.IMetadataSection; @SideOnly(Side.CLIENT) @@ -16,7 +14,8 @@ public class ColorsMetadataSection implements IMetadataSection { private final Map hexGuiTints; private final boolean guiTintEnabled; - public ColorsMetadataSection(Map hexTextColorMap, Map hexGuiTintMap, boolean guiTintEnabled) { + public ColorsMetadataSection( + Map hexTextColorMap, Map hexGuiTintMap, boolean guiTintEnabled) { this.hexTextColors = hexTextColorMap; this.textColors = convertHexMapToIntMap(hexTextColorMap); @@ -26,16 +25,15 @@ public class ColorsMetadataSection implements IMetadataSection { this.guiTintEnabled = guiTintEnabled; } - private Map convertHexMapToIntMap(Map hexMap) { + private Map convertHexMapToIntMap(Map hexMap) { Map intMap = new HashMap<>(); for (String key : hexMap.keySet()) { int colorValue = -1; String hex = hexMap.get(key); try { - if (!hex.isEmpty()) colorValue = Integer.parseUnsignedInt(hex,16); - } - catch (final NumberFormatException e) { + if (!hex.isEmpty()) colorValue = Integer.parseUnsignedInt(hex, 16); + } catch (final NumberFormatException e) { GT_Log.err.println("Couldn't format color correctly of " + key + " -> " + hex); } intMap.put(key, colorValue); @@ -51,7 +49,7 @@ public class ColorsMetadataSection implements IMetadataSection { return sColorInMap(key, this.hexGuiTints) ? defaultColor : this.guiTints.get(key); } - private boolean sColorInMap(String key, Map hexMap) { + private boolean sColorInMap(String key, Map hexMap) { return hexMap.containsKey(key) && hexMap.get(key).isEmpty(); } diff --git a/src/main/java/gregtech/api/util/ColorsMetadataSectionSerializer.java b/src/main/java/gregtech/api/util/ColorsMetadataSectionSerializer.java index 4de8463685..718ff81854 100644 --- a/src/main/java/gregtech/api/util/ColorsMetadataSectionSerializer.java +++ b/src/main/java/gregtech/api/util/ColorsMetadataSectionSerializer.java @@ -7,26 +7,29 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import java.lang.reflect.Type; -import java.util.Map; -import java.util.HashMap; import gregtech.api.GregTech_API; import gregtech.api.enums.Dyes; -import net.minecraft.util.JsonUtils; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; import net.minecraft.client.resources.data.BaseMetadataSectionSerializer; +import net.minecraft.util.JsonUtils; @SideOnly(Side.CLIENT) public class ColorsMetadataSectionSerializer extends BaseMetadataSectionSerializer implements JsonSerializer { - public ColorsMetadataSection deserialize(JsonElement metadataColors, Type type, JsonDeserializationContext context) { + public ColorsMetadataSection deserialize( + JsonElement metadataColors, Type type, JsonDeserializationContext context) { // Default values boolean enableGuiTint = GregTech_API.sColoredGUI; Map hexGuiTintMap = new HashMap(); - Map hexTextColorMap = new HashMap() {{ - put("title", ""); - put("text", ""); - put("value", ""); - put("nei", ""); - }}; + Map hexTextColorMap = new HashMap() { + { + put("title", ""); + put("text", ""); + put("value", ""); + put("nei", ""); + } + }; JsonObject jsonObject = JsonUtils.getJsonElementAsJsonObject(metadataColors, "metadata section"); if (jsonObject.has("textColor")) { @@ -38,7 +41,8 @@ public class ColorsMetadataSectionSerializer extends BaseMetadataSectionSerializ if (jsonObject.has("guiTint")) { JsonObject guiTints = JsonUtils.func_152754_s(jsonObject, "guiTint"); - enableGuiTint = JsonUtils.getJsonObjectBooleanFieldValueOrDefault(guiTints, "enableGuiTintWhenPainted", true); + enableGuiTint = + JsonUtils.getJsonObjectBooleanFieldValueOrDefault(guiTints, "enableGuiTintWhenPainted", true); for (Dyes dye : Dyes.values()) { hexGuiTintMap.put(dye.mName, GT_Util.toHexString(dye.getRGBA())); @@ -46,7 +50,9 @@ public class ColorsMetadataSectionSerializer extends BaseMetadataSectionSerializ for (String key : hexGuiTintMap.keySet()) { if (enableGuiTint) { - hexGuiTintMap.replace(key, JsonUtils.getJsonObjectStringFieldValueOrDefault(guiTints, key, hexGuiTintMap.get(key))); + hexGuiTintMap.replace( + key, + JsonUtils.getJsonObjectStringFieldValueOrDefault(guiTints, key, hexGuiTintMap.get(key))); } else { hexGuiTintMap.replace(key, GT_Util.toHexString(Dyes.dyeWhite.getRGBA())); } diff --git a/src/main/java/gregtech/api/util/GT_ApiaryUpgrade.java b/src/main/java/gregtech/api/util/GT_ApiaryUpgrade.java index e74b68111a..4cbd014cbc 100644 --- a/src/main/java/gregtech/api/util/GT_ApiaryUpgrade.java +++ b/src/main/java/gregtech/api/util/GT_ApiaryUpgrade.java @@ -3,13 +3,12 @@ package gregtech.api.util; import cpw.mods.fml.common.Loader; import gregtech.api.enums.OrePrefixes; import gregtech.common.items.GT_MetaGenerated_Item_03; +import java.util.*; +import java.util.function.Consumer; import net.bdew.gendustry.api.ApiaryModifiers; import net.bdew.gendustry.api.items.IApiaryUpgrade; import net.minecraft.item.ItemStack; -import java.util.*; -import java.util.function.Consumer; - public enum GT_ApiaryUpgrade { speed1(UNIQUE_INDEX.SPEED_UPGRADE, 32200, 1, 1), speed2(UNIQUE_INDEX.SPEED_UPGRADE, 32201, 1, 2), @@ -22,15 +21,17 @@ public enum GT_ApiaryUpgrade { speed8upgraded(UNIQUE_INDEX.SPEED_UPGRADE, 32208, 1, 8), ; - private enum UNIQUE_INDEX{ + private enum UNIQUE_INDEX { SPEED_UPGRADE, ; - void apply(Consumer fn){ + + void apply(Consumer fn) { UNIQUE_UPGRADE_LIST.get(this).forEach(fn); } } - private static final EnumMap> UNIQUE_UPGRADE_LIST = new EnumMap<>(UNIQUE_INDEX.class); + private static final EnumMap> UNIQUE_UPGRADE_LIST = + new EnumMap<>(UNIQUE_INDEX.class); private int meta = 0; private int maxnumber = 1; @@ -40,9 +41,10 @@ public enum GT_ApiaryUpgrade { private final UNIQUE_INDEX unique_index; private final HashMap additionalGendustryUpgrades = new HashMap<>(); - private final HashSet blacklistedUpgrades = new HashSet<>(); // additionalGendustryUpgrades are blacklisted by default + private final HashSet blacklistedUpgrades = + new HashSet<>(); // additionalGendustryUpgrades are blacklisted by default - GT_ApiaryUpgrade(UNIQUE_INDEX unique_index, int meta, int maxnumber, int maxspeedmodifier){ + GT_ApiaryUpgrade(UNIQUE_INDEX unique_index, int meta, int maxnumber, int maxspeedmodifier) { this.unique_index = unique_index; this.meta = meta; this.maxnumber = maxnumber; @@ -50,11 +52,14 @@ public enum GT_ApiaryUpgrade { this.id = GT_Utility.ItemId.createNoCopy(get(1)); } - private void setup_static_variables(){ + private void setup_static_variables() { quickLookup.put(this.meta, this); ArrayList un = UNIQUE_UPGRADE_LIST.get(this.unique_index); - if(un != null) - un.forEach((u) -> { u.blacklistedUpgrades.add(this.id); this.blacklistedUpgrades.add(u.id); }); + if (un != null) + un.forEach((u) -> { + u.blacklistedUpgrades.add(this.id); + this.blacklistedUpgrades.add(u.id); + }); else { un = new ArrayList<>(1); UNIQUE_UPGRADE_LIST.put(this.unique_index, un); @@ -62,45 +67,43 @@ public enum GT_ApiaryUpgrade { un.add(this); } - public static GT_ApiaryUpgrade getUpgrade(ItemStack s){ - if(s == null) - return null; - if(!isUpgrade(s)) - return null; + public static GT_ApiaryUpgrade getUpgrade(ItemStack s) { + if (s == null) return null; + if (!isUpgrade(s)) return null; return quickLookup.get(s.getItemDamage()); } - public boolean isAllowedToWorkWith(ItemStack s){ + public boolean isAllowedToWorkWith(ItemStack s) { GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(s); return !additionalGendustryUpgrades.containsKey(id) && !blacklistedUpgrades.contains(id); } - public int getMaxNumber(){ + public int getMaxNumber() { return maxnumber; } - public void applyModifiers(ApiaryModifiers mods, ItemStack s){ - additionalGendustryUpgrades.forEach((k, u) -> ((IApiaryUpgrade)u.getItem()).applyModifiers(mods, u)); + public void applyModifiers(ApiaryModifiers mods, ItemStack s) { + additionalGendustryUpgrades.forEach((k, u) -> ((IApiaryUpgrade) u.getItem()).applyModifiers(mods, u)); } - public ItemStack get(int count){ + public ItemStack get(int count) { return new ItemStack(GT_MetaGenerated_Item_03.INSTANCE, count, meta); } - public static boolean isUpgrade(ItemStack s){ + public static boolean isUpgrade(ItemStack s) { return OrePrefixes.apiaryUpgrade.contains(s); } - public int applyMaxSpeedModifier(int maxspeed){ + public int applyMaxSpeedModifier(int maxspeed) { return Math.max(maxspeed, maxspeedmodifier); } private static final HashMap quickLookup = new HashMap<>(); - static{ + static { EnumSet.allOf(GT_ApiaryUpgrade.class).forEach(GT_ApiaryUpgrade::setup_static_variables); - if(Loader.isModLoaded("gendustry")) { + if (Loader.isModLoaded("gendustry")) { ItemStack s = GT_ModHandler.getModItem("gendustry", "ApiaryUpgrade", 8L, 0); GT_Utility.ItemId a = GT_Utility.ItemId.createNoCopy(s); speed8upgraded.additionalGendustryUpgrades.put(a, s); diff --git a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java index 4f9036f2c7..f20a78d494 100644 --- a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java +++ b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java @@ -2,17 +2,17 @@ package gregtech.api.util; import static gregtech.GT_Mod.GT_FML_LOGGER; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; - import cpw.mods.fml.common.FMLCommonHandler; import gregtech.api.enums.GT_Values; import gregtech.api.enums.ItemList; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.GT_Recipe.GT_Recipe_AssemblyLine; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -20,509 +20,514 @@ import net.minecraft.nbt.NBTTagString; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fluids.FluidStack; -import javax.annotation.Nonnull; - public class GT_AssemblyLineUtils { - /** - * A cache of Recipes using the Output as Key. - */ - private static HashMap sRecipeCacheByOutput = new HashMap(); - /** - * A cache of Recipes using the Recipe Hash String as Key. - */ - private static HashMap sRecipeCacheByRecipeHash = new HashMap(); - - - - /** - * Checks the DataStick for deprecated/invalid recipes, updating them as required. - * @param aDataStick - The DataStick to process - * @return Is this DataStick now valid with a current recipe? - */ - public static GT_Recipe_AssemblyLine processDataStick(ItemStack aDataStick) { - if (!isItemDataStick(aDataStick)) { - return null; - } - if (doesDataStickNeedUpdate(aDataStick)) { - ItemStack aStickOutput = getDataStickOutput(aDataStick); - if (aStickOutput != null) { - GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); - if (aIntendedRecipe != null && setAssemblyLineRecipeOnDataStick(aDataStick, aIntendedRecipe)) - return aIntendedRecipe; - } - } - return null; - } - - - /** - * Finds an Assembly Line recipe from a DataStick. - * @param aDataStick - The DataStick to check. - * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. - */ - public static GT_Recipe_AssemblyLine findAssemblyLineRecipeFromDataStick(ItemStack aDataStick) { - return findAssemblyLineRecipeFromDataStick(aDataStick, false).getRecipe(); - } - - /** - * Finds an Assembly Line recipe from a DataStick. - * @param aDataStick - The DataStick to check. - * @param aReturnBuiltRecipe - Do we return a GT_Recipe_AssemblyLine built from the data on the Data Stick instead of searching the Recipe Map? - * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. - */ - @Nonnull - public static LookupResult findAssemblyLineRecipeFromDataStick(ItemStack aDataStick, boolean aReturnBuiltRecipe) { - if (!isItemDataStick(aDataStick) || !doesDataStickHaveOutput(aDataStick)) { - return LookupResultType.INVALID_STICK.getResult(); - } - List aInputs = new ArrayList<>(15); - ItemStack aOutput = getDataStickOutput(aDataStick); - List> mOreDictAlt = new ArrayList<>(15); - List aFluidInputs = new ArrayList<>(4); - - NBTTagCompound aTag = aDataStick.getTagCompound(); - if (aTag == null) { - return LookupResultType.INVALID_STICK.getResult(); - } - - //Get From Cache - if (doesDataStickHaveRecipeHash(aDataStick)) { - GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByRecipeHash.get(getHashFromDataStack(aDataStick)); - if (aRecipeFromCache != null && GT_Utility.areStacksEqual(aOutput, aRecipeFromCache.mOutput)) { - return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipeFromCache); - } // else: no cache, or the old recipe run into a hash collision with a different new recipe - } - - for (int i = 0; i < 15; i++) { - int count = aTag.getInteger("a" + i); - if (!aTag.hasKey("" + i) && count <= 0) { - continue; - } - - List tAltCurrent = new ArrayList<>(); - for (int j = 0; j < count; j++) { - ItemStack tLoaded = GT_Utility.loadItem(aTag, "a" + i + ":" + j); - if (tLoaded == null) { - continue; - } - tAltCurrent.add(tLoaded); - if (GT_Values.D1) { - GT_FML_LOGGER.info("Item Alt " + i + " : " + tLoaded.getUnlocalizedName()); - } - } - mOreDictAlt.add(tAltCurrent); - ItemStack tLoaded = GT_Utility.loadItem(aTag, "" + i); - if (tLoaded == null) { - continue; - } - aInputs.add(tLoaded); - if (GT_Values.D1) { - GT_FML_LOGGER.info("Item " + i + " : " + tLoaded.getUnlocalizedName()); - } - } - - if (GT_Values.D1) { - GT_FML_LOGGER.info("All Items done, start fluid check"); - } - for (int i = 0; i < 4; i++) { - if (!aTag.hasKey("f" + i)) continue; - FluidStack tLoaded = GT_Utility.loadFluid(aTag, "f" + i); - if (tLoaded == null) continue; - aFluidInputs.add(tLoaded); - if (GT_Values.D1) { - GT_FML_LOGGER.info("Fluid " + i + " " + tLoaded.getUnlocalizedName()); - } - } - if (!aTag.hasKey("output") || !aTag.hasKey("time") || aTag.getInteger("time") <= 0 || !aTag.hasKey("eu") || !GT_Utility.isStackValid(aOutput)) { - return LookupResultType.INVALID_STICK.getResult(); - } - if (GT_Values.D1) { - GT_FML_LOGGER.info("Found Data Stick recipe"); - } - - int aTime = aTag.getInteger("time"); - int aEU = aTag.getInteger("eu"); - - // Try build a recipe instance - if (aReturnBuiltRecipe) { - return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(new GT_Recipe_AssemblyLine(null, 0, aInputs.toArray(new ItemStack[0]), aFluidInputs.toArray(new FluidStack[0]), aOutput, aTime, aEU)); - } - - - for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { - if (aRecipe.mEUt != aEU || aRecipe.mDuration != aTime) continue; - if (!GT_Utility.areStacksEqual(aOutput, aRecipe.mOutput, true)) continue; - if (!GT_Utility.areStackListsEqual(Arrays.asList(aRecipe.mInputs), aInputs, false, true)) continue; - if (!Objects.equals(Arrays.asList(aRecipe.mFluidInputs), aFluidInputs)) continue; - if (!areStacksEqual(aRecipe.mOreDictAlt, mOreDictAlt)) continue; - - // Cache it - String aRecipeHash = generateRecipeHash(aRecipe); - sRecipeCacheByRecipeHash.put(aRecipeHash, aRecipe); - sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); - if (doesDataStickHaveRecipeHash(aDataStick)) { - String aStickHash = getHashFromDataStack(aDataStick); - if (aRecipeHash.equals(aStickHash)) - return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipe); - } - return LookupResultType.VALID_STACK_AND_VALID_RECIPE.getResult(aRecipe); - } - return LookupResultType.VALID_STACK_BUT_INVALID_RECIPE.getResult(); - } - - private static boolean areStacksEqual(ItemStack[][] lhs, List> rhs) { - for (int i = 0; i < lhs.length; i++) { - if (!areStacksEqual(lhs[i], rhs.get(i))) - return false; - } - return true; - } - - private static boolean areStacksEqual(ItemStack[] lhs, List rhs) { - return lhs == null ? rhs.isEmpty() : !rhs.isEmpty() && GT_Utility.areStackListsEqual(Arrays.asList(lhs), rhs, false, true); - } - - - /** - * Finds a GT_Recipe_AssemblyLine based on the expected output ItemStack. - * @param aOutput - The Output of a GT_Recipe_AssemblyLine. - * @return First found GT_Recipe_AssemblyLine with matching output. - */ - public static GT_Recipe_AssemblyLine findAssemblyLineRecipeByOutput(ItemStack aOutput) { - if (aOutput == null) { - return null; - } - - // Check the cache - GT_ItemStack aCacheStack = new GT_ItemStack(aOutput); - GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByOutput.get(aCacheStack); - if (aRecipeFromCache != null) { - return aRecipeFromCache; - } - - // Iterate all recipes and return the first matching based on Output. - for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { - ItemStack aRecipeOutput = aRecipe.mOutput; - if (GT_Utility.areStacksEqual(aRecipeOutput, aOutput)) { - // Cache it to prevent future iterations of all recipes - sRecipeCacheByOutput.put(aCacheStack, aRecipe); - sRecipeCacheByRecipeHash.put(generateRecipeHash(aRecipe), aRecipe); - return aRecipe; - } - } - return null; - } - - /** - * @param aRecipe - The recipe to generate a Recipe Hash String from. - * @return The Recipe Hash String. - */ - public static String generateRecipeHash(GT_Recipe_AssemblyLine aRecipe) { - String aHash = "Invalid.Recipe.Hash"; - if (aRecipe != null) { - aHash = "Hash."+aRecipe.getPersistentHash(); - } - return aHash; - } - - /** - * @param aRecipe - The recipe to add to internal caches - * @throws IllegalArgumentException if given recipe collide with any existing recipe in the cache - */ - public static void addRecipeToCache(GT_Recipe_AssemblyLine aRecipe) { - if (aRecipe != null) { - String aHash = "Hash." + aRecipe.getPersistentHash(); - GT_Recipe_AssemblyLine existing = sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); - if (existing != null) - throw new IllegalArgumentException("Duplicate assline recipe for " + aRecipe.mOutput); - existing = sRecipeCacheByRecipeHash.put(aHash, aRecipe); - if (existing != null && !existing.equals(aRecipe)) - throw new IllegalArgumentException("Recipe hash collision for " + aRecipe + " and " + existing); - } - } - - /** - * @param aHash - Recipe hash String, may be null but will just be treated as invalid. - * @return Is this Recipe Hash String valid? - */ - public static boolean isValidHash(String aHash) { - if (aHash != null && aHash.length() > 0) { - // persistent hash can never be 0 - return !aHash.equals("Invalid.Recipe.Hash") && !aHash.equals("Hash.0"); - } - return false; - } - - /** - * @param aStack - The ItemStack to check. - * @return Is this ItemStack a Data Stick? - */ - public static boolean isItemDataStick(ItemStack aStack) { - return GT_Utility.isStackValid(aStack) && ItemList.Tool_DataStick.isStackEqual(aStack, false, true); - } - - /** - * @param aDataStick - The Data Stick to check. - * @return Does this Data Stick have a valid output ItemStack? - */ - public static boolean doesDataStickHaveOutput(ItemStack aDataStick) { - if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound() && aDataStick.getTagCompound().hasKey("output")) { - return true; - } - return false; - } - - /** - * @param aDataStick - The Data Stick to check. - * @return Does this Data Stick need recipe data updated. - */ - public static boolean doesDataStickNeedUpdate(ItemStack aDataStick) { - if (isItemDataStick(aDataStick) && doesDataStickHaveRecipeHash(aDataStick)) { - String aStickHash = getHashFromDataStack(aDataStick); - if (isValidHash(aStickHash) && doesDataStickHaveOutput(aDataStick)) { - ItemStack aStickOutput = getDataStickOutput(aDataStick); - GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); - if (aStickHash.equals(generateRecipeHash(aIntendedRecipe))) { - return false; - } - } - } - return true; - } - - /** - * @param aDataStick - The Data Stick to check. - * @return Does this have a Recipe Hash String at all? - */ - public static boolean doesDataStickHaveRecipeHash(ItemStack aDataStick) { - if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { - NBTTagCompound aNBT = aDataStick.getTagCompound(); - if (aNBT.hasKey("Data.Recipe.Hash") && !aNBT.getString("Data.Recipe.Hash").equals("Hash.0")) { - return true; - } - } - return false; - } - - /** - * Get the Output ItemStack from a Data Stick. - * @param aDataStick - The Data Stick to check. - * @return Output ItemStack contained on the Data Stick. - */ - public static ItemStack getDataStickOutput(ItemStack aDataStick) { - if (doesDataStickHaveOutput(aDataStick)) { - ItemStack aOutput = GT_Utility.loadItem(aDataStick.getTagCompound(), "output"); - return aOutput; - } - return null; - } - - /** - * @param aDataStick - The Data Stick to process. - * @return The stored Recipe Hash String on the Data Stick, will return an invalid Hash if one is not found.

- * The hash will be guaranteed to pass isValidHash().

- * Will not return Null. - */ - public static String getHashFromDataStack(ItemStack aDataStick) { - if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { - NBTTagCompound aNBT = aDataStick.getTagCompound(); - if (aNBT.hasKey("Data.Recipe.Hash", NBT.TAG_STRING)) { - String hash = aNBT.getString("Data.Recipe.Hash"); - if (isValidHash(hash)) - return hash; - } - } - return "Invalid.Recipe.Hash"; - } - - /** - * - * @param aDataStick - The Data Stick to update. - * @param aRecipeHash - The Recipe Hash String to update with. - * @return Did we update the Recipe Hash String on the Data Stick? - */ - public static boolean setRecipeHashOnDataStick(ItemStack aDataStick, String aRecipeHash) { - if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { - NBTTagCompound aNBT = aDataStick.getTagCompound(); - aNBT.setString("Data.Recipe.Hash", aRecipeHash); - aDataStick.setTagCompound(aNBT); - return true; - } - return false; - } - - /** - * - * @param aDataStick - The Data Stick to update. - * @param aNewRecipe - The New GT_Recipe_AssemblyLine recipe to update it with. - * @return Did we set the new recipe data & Recipe Hash String on the Data Stick? - */ - public static boolean setAssemblyLineRecipeOnDataStick(ItemStack aDataStick, GT_Recipe_AssemblyLine aNewRecipe) { - if (isItemDataStick(aDataStick)) { - String s = aNewRecipe.mOutput.getDisplayName(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); - if (s == null) { - s = aNewRecipe.mOutput.getDisplayName(); - } - } - - String aHash = generateRecipeHash(aNewRecipe); - if (GT_Values.D1) { - GT_Recipe_AssemblyLine aOldRecipe = findAssemblyLineRecipeFromDataStick(aDataStick, true).recipe; - GT_FML_LOGGER.info("Updating data stick: "+aDataStick.getDisplayName()+" | Old Recipe Hash: "+generateRecipeHash(aOldRecipe)+", New Recipe Hash: "+aHash); - } - - String author = "Assembling Line Recipe Generator"; - String displayName = null; - if (aDataStick.hasTagCompound()) { - NBTTagCompound tag = aDataStick.getTagCompound(); - if (tag.hasKey("author", NBT.TAG_STRING)) { - author = tag.getString("author"); - } - if (tag.hasKey("display", NBT.TAG_COMPOUND)) { - NBTTagCompound displayTag = tag.getCompoundTag("display"); - if (displayTag.hasKey("Name", NBT.TAG_STRING)) - displayName = displayTag.getString("Name"); - } - } - - //remove possible old NBTTagCompound - aDataStick.setTagCompound(new NBTTagCompound()); - if (displayName != null) - aDataStick.setStackDisplayName(displayName); - if (GT_Values.D1) { - GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data ("+aHash+")"); - } - else { - GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data"); - } - - NBTTagCompound tNBT = aDataStick.getTagCompound(); - if (tNBT == null) { - tNBT = new NBTTagCompound(); - } - - tNBT.setTag("output", aNewRecipe.mOutput.writeToNBT(new NBTTagCompound())); - tNBT.setInteger("time", aNewRecipe.mDuration); - tNBT.setInteger("eu", aNewRecipe.mEUt); - for (int i = 0; i < aNewRecipe.mInputs.length; i++) { - tNBT.setTag("" + i, aNewRecipe.mInputs[i].writeToNBT(new NBTTagCompound())); - } - for (int i = 0; i < aNewRecipe.mOreDictAlt.length; i++) { - if (aNewRecipe.mOreDictAlt[i] != null && aNewRecipe.mOreDictAlt[i].length > 0) { - tNBT.setInteger("a" + i, aNewRecipe.mOreDictAlt[i].length); - for (int j = 0; j < aNewRecipe.mOreDictAlt[i].length; j++) { - tNBT.setTag("a" + i + ":" + j, aNewRecipe.mOreDictAlt[i][j].writeToNBT(new NBTTagCompound())); - } - } - } - for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { - tNBT.setTag("f" + i, aNewRecipe.mFluidInputs[i].writeToNBT(new NBTTagCompound())); - } - tNBT.setString("author", author); - NBTTagList tNBTList = new NBTTagList(); - s = aNewRecipe.mOutput.getDisplayName(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); - if (s == null) - s = aNewRecipe.mOutput.getDisplayName(); - } - tNBTList.appendTag(new NBTTagString("Construction plan for " + aNewRecipe.mOutput.stackSize + " " + s + ". Needed EU/t: " + aNewRecipe.mEUt + " Production time: " + (aNewRecipe.mDuration / 20))); - for (int i = 0; i < aNewRecipe.mInputs.length; i++) { - if (aNewRecipe.mOreDictAlt[i] != null) { - int count = 0; - StringBuilder tBuilder = new StringBuilder("Input Bus " + (i + 1) + ": "); - for (ItemStack tStack : aNewRecipe.mOreDictAlt[i]) { - if (tStack != null) { - s = tStack.getDisplayName(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - s = GT_Assemblyline_Server.lServerNames.get(tStack.getDisplayName()); - if (s == null) - s = tStack.getDisplayName(); - } - - - tBuilder.append(count == 0 ? "" : "\nOr ").append(tStack.stackSize).append(" ").append(s); - count++; - } - } - if (count > 0) tNBTList.appendTag(new NBTTagString(tBuilder.toString())); - } else if (aNewRecipe.mInputs[i] != null) { - s = aNewRecipe.mInputs[i].getDisplayName(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mInputs[i].getDisplayName()); - if (s == null) - s = aNewRecipe.mInputs[i].getDisplayName(); - } - tNBTList.appendTag(new NBTTagString("Input Bus " + (i + 1) + ": " + aNewRecipe.mInputs[i].stackSize + " " + s)); - } - } - for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { - if (aNewRecipe.mFluidInputs[i] != null) { - s = aNewRecipe.mFluidInputs[i].getLocalizedName(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mFluidInputs[i].getLocalizedName()); - if (s == null) - s = aNewRecipe.mFluidInputs[i].getLocalizedName(); - } - tNBTList.appendTag(new NBTTagString("Input Hatch " + (i + 1) + ": " + aNewRecipe.mFluidInputs[i].amount + "L " + s)); - } - } - tNBT.setTag("pages", tNBTList); - tNBT.setLong("lastUpdate", System.currentTimeMillis()); - aDataStick.setTagCompound(tNBT); - // Set recipe hash - setRecipeHashOnDataStick(aDataStick, aHash); - return true; - } - return false; - } - - public enum LookupResultType { - INVALID_STICK(true), - VALID_STACK_BUT_INVALID_RECIPE(true), - VALID_STACK_AND_VALID_RECIPE(false), - VALID_STACK_AND_VALID_HASH(false); - - private final boolean recipeNull; - private LookupResult singletonResult; - - LookupResultType(boolean recipeNull) { - this.recipeNull = recipeNull; - } - - public LookupResult getResult() { - if (!recipeNull) - throw new IllegalArgumentException("This result type require a nonnull recipe"); - if (singletonResult == null) - singletonResult = new LookupResult(null, this); - return singletonResult; - } - - public LookupResult getResult(GT_Recipe_AssemblyLine recipe) { - if ((recipe == null) != recipeNull) - throw new IllegalArgumentException("This result type does not allow given input"); - return new LookupResult(recipe, this); - } - } - - public static class LookupResult { - private final GT_Recipe_AssemblyLine recipe; - private final LookupResultType type; - - LookupResult(GT_Recipe_AssemblyLine recipe, LookupResultType type) { - this.recipe = recipe; - this.type = type; - } - - public GT_Recipe_AssemblyLine getRecipe() { - return recipe; - } - - public LookupResultType getType() { - return type; - } - } + /** + * A cache of Recipes using the Output as Key. + */ + private static HashMap sRecipeCacheByOutput = + new HashMap(); + /** + * A cache of Recipes using the Recipe Hash String as Key. + */ + private static HashMap sRecipeCacheByRecipeHash = + new HashMap(); + + /** + * Checks the DataStick for deprecated/invalid recipes, updating them as required. + * @param aDataStick - The DataStick to process + * @return Is this DataStick now valid with a current recipe? + */ + public static GT_Recipe_AssemblyLine processDataStick(ItemStack aDataStick) { + if (!isItemDataStick(aDataStick)) { + return null; + } + if (doesDataStickNeedUpdate(aDataStick)) { + ItemStack aStickOutput = getDataStickOutput(aDataStick); + if (aStickOutput != null) { + GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); + if (aIntendedRecipe != null && setAssemblyLineRecipeOnDataStick(aDataStick, aIntendedRecipe)) + return aIntendedRecipe; + } + } + return null; + } + + /** + * Finds an Assembly Line recipe from a DataStick. + * @param aDataStick - The DataStick to check. + * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. + */ + public static GT_Recipe_AssemblyLine findAssemblyLineRecipeFromDataStick(ItemStack aDataStick) { + return findAssemblyLineRecipeFromDataStick(aDataStick, false).getRecipe(); + } + + /** + * Finds an Assembly Line recipe from a DataStick. + * @param aDataStick - The DataStick to check. + * @param aReturnBuiltRecipe - Do we return a GT_Recipe_AssemblyLine built from the data on the Data Stick instead of searching the Recipe Map? + * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. + */ + @Nonnull + public static LookupResult findAssemblyLineRecipeFromDataStick(ItemStack aDataStick, boolean aReturnBuiltRecipe) { + if (!isItemDataStick(aDataStick) || !doesDataStickHaveOutput(aDataStick)) { + return LookupResultType.INVALID_STICK.getResult(); + } + List aInputs = new ArrayList<>(15); + ItemStack aOutput = getDataStickOutput(aDataStick); + List> mOreDictAlt = new ArrayList<>(15); + List aFluidInputs = new ArrayList<>(4); + + NBTTagCompound aTag = aDataStick.getTagCompound(); + if (aTag == null) { + return LookupResultType.INVALID_STICK.getResult(); + } + + // Get From Cache + if (doesDataStickHaveRecipeHash(aDataStick)) { + GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByRecipeHash.get(getHashFromDataStack(aDataStick)); + if (aRecipeFromCache != null && GT_Utility.areStacksEqual(aOutput, aRecipeFromCache.mOutput)) { + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipeFromCache); + } // else: no cache, or the old recipe run into a hash collision with a different new recipe + } + + for (int i = 0; i < 15; i++) { + int count = aTag.getInteger("a" + i); + if (!aTag.hasKey("" + i) && count <= 0) { + continue; + } + + List tAltCurrent = new ArrayList<>(); + for (int j = 0; j < count; j++) { + ItemStack tLoaded = GT_Utility.loadItem(aTag, "a" + i + ":" + j); + if (tLoaded == null) { + continue; + } + tAltCurrent.add(tLoaded); + if (GT_Values.D1) { + GT_FML_LOGGER.info("Item Alt " + i + " : " + tLoaded.getUnlocalizedName()); + } + } + mOreDictAlt.add(tAltCurrent); + ItemStack tLoaded = GT_Utility.loadItem(aTag, "" + i); + if (tLoaded == null) { + continue; + } + aInputs.add(tLoaded); + if (GT_Values.D1) { + GT_FML_LOGGER.info("Item " + i + " : " + tLoaded.getUnlocalizedName()); + } + } + + if (GT_Values.D1) { + GT_FML_LOGGER.info("All Items done, start fluid check"); + } + for (int i = 0; i < 4; i++) { + if (!aTag.hasKey("f" + i)) continue; + FluidStack tLoaded = GT_Utility.loadFluid(aTag, "f" + i); + if (tLoaded == null) continue; + aFluidInputs.add(tLoaded); + if (GT_Values.D1) { + GT_FML_LOGGER.info("Fluid " + i + " " + tLoaded.getUnlocalizedName()); + } + } + if (!aTag.hasKey("output") + || !aTag.hasKey("time") + || aTag.getInteger("time") <= 0 + || !aTag.hasKey("eu") + || !GT_Utility.isStackValid(aOutput)) { + return LookupResultType.INVALID_STICK.getResult(); + } + if (GT_Values.D1) { + GT_FML_LOGGER.info("Found Data Stick recipe"); + } + + int aTime = aTag.getInteger("time"); + int aEU = aTag.getInteger("eu"); + + // Try build a recipe instance + if (aReturnBuiltRecipe) { + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(new GT_Recipe_AssemblyLine( + null, + 0, + aInputs.toArray(new ItemStack[0]), + aFluidInputs.toArray(new FluidStack[0]), + aOutput, + aTime, + aEU)); + } + + for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { + if (aRecipe.mEUt != aEU || aRecipe.mDuration != aTime) continue; + if (!GT_Utility.areStacksEqual(aOutput, aRecipe.mOutput, true)) continue; + if (!GT_Utility.areStackListsEqual(Arrays.asList(aRecipe.mInputs), aInputs, false, true)) continue; + if (!Objects.equals(Arrays.asList(aRecipe.mFluidInputs), aFluidInputs)) continue; + if (!areStacksEqual(aRecipe.mOreDictAlt, mOreDictAlt)) continue; + + // Cache it + String aRecipeHash = generateRecipeHash(aRecipe); + sRecipeCacheByRecipeHash.put(aRecipeHash, aRecipe); + sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); + if (doesDataStickHaveRecipeHash(aDataStick)) { + String aStickHash = getHashFromDataStack(aDataStick); + if (aRecipeHash.equals(aStickHash)) + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipe); + } + return LookupResultType.VALID_STACK_AND_VALID_RECIPE.getResult(aRecipe); + } + return LookupResultType.VALID_STACK_BUT_INVALID_RECIPE.getResult(); + } + + private static boolean areStacksEqual(ItemStack[][] lhs, List> rhs) { + for (int i = 0; i < lhs.length; i++) { + if (!areStacksEqual(lhs[i], rhs.get(i))) return false; + } + return true; + } + + private static boolean areStacksEqual(ItemStack[] lhs, List rhs) { + return lhs == null + ? rhs.isEmpty() + : !rhs.isEmpty() && GT_Utility.areStackListsEqual(Arrays.asList(lhs), rhs, false, true); + } + + /** + * Finds a GT_Recipe_AssemblyLine based on the expected output ItemStack. + * @param aOutput - The Output of a GT_Recipe_AssemblyLine. + * @return First found GT_Recipe_AssemblyLine with matching output. + */ + public static GT_Recipe_AssemblyLine findAssemblyLineRecipeByOutput(ItemStack aOutput) { + if (aOutput == null) { + return null; + } + + // Check the cache + GT_ItemStack aCacheStack = new GT_ItemStack(aOutput); + GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByOutput.get(aCacheStack); + if (aRecipeFromCache != null) { + return aRecipeFromCache; + } + + // Iterate all recipes and return the first matching based on Output. + for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { + ItemStack aRecipeOutput = aRecipe.mOutput; + if (GT_Utility.areStacksEqual(aRecipeOutput, aOutput)) { + // Cache it to prevent future iterations of all recipes + sRecipeCacheByOutput.put(aCacheStack, aRecipe); + sRecipeCacheByRecipeHash.put(generateRecipeHash(aRecipe), aRecipe); + return aRecipe; + } + } + return null; + } + + /** + * @param aRecipe - The recipe to generate a Recipe Hash String from. + * @return The Recipe Hash String. + */ + public static String generateRecipeHash(GT_Recipe_AssemblyLine aRecipe) { + String aHash = "Invalid.Recipe.Hash"; + if (aRecipe != null) { + aHash = "Hash." + aRecipe.getPersistentHash(); + } + return aHash; + } + + /** + * @param aRecipe - The recipe to add to internal caches + * @throws IllegalArgumentException if given recipe collide with any existing recipe in the cache + */ + public static void addRecipeToCache(GT_Recipe_AssemblyLine aRecipe) { + if (aRecipe != null) { + String aHash = "Hash." + aRecipe.getPersistentHash(); + GT_Recipe_AssemblyLine existing = sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); + if (existing != null) throw new IllegalArgumentException("Duplicate assline recipe for " + aRecipe.mOutput); + existing = sRecipeCacheByRecipeHash.put(aHash, aRecipe); + if (existing != null && !existing.equals(aRecipe)) + throw new IllegalArgumentException("Recipe hash collision for " + aRecipe + " and " + existing); + } + } + + /** + * @param aHash - Recipe hash String, may be null but will just be treated as invalid. + * @return Is this Recipe Hash String valid? + */ + public static boolean isValidHash(String aHash) { + if (aHash != null && aHash.length() > 0) { + // persistent hash can never be 0 + return !aHash.equals("Invalid.Recipe.Hash") && !aHash.equals("Hash.0"); + } + return false; + } + + /** + * @param aStack - The ItemStack to check. + * @return Is this ItemStack a Data Stick? + */ + public static boolean isItemDataStick(ItemStack aStack) { + return GT_Utility.isStackValid(aStack) && ItemList.Tool_DataStick.isStackEqual(aStack, false, true); + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this Data Stick have a valid output ItemStack? + */ + public static boolean doesDataStickHaveOutput(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) + && aDataStick.hasTagCompound() + && aDataStick.getTagCompound().hasKey("output")) { + return true; + } + return false; + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this Data Stick need recipe data updated. + */ + public static boolean doesDataStickNeedUpdate(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && doesDataStickHaveRecipeHash(aDataStick)) { + String aStickHash = getHashFromDataStack(aDataStick); + if (isValidHash(aStickHash) && doesDataStickHaveOutput(aDataStick)) { + ItemStack aStickOutput = getDataStickOutput(aDataStick); + GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); + if (aStickHash.equals(generateRecipeHash(aIntendedRecipe))) { + return false; + } + } + } + return true; + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this have a Recipe Hash String at all? + */ + public static boolean doesDataStickHaveRecipeHash(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + if (aNBT.hasKey("Data.Recipe.Hash") + && !aNBT.getString("Data.Recipe.Hash").equals("Hash.0")) { + return true; + } + } + return false; + } + + /** + * Get the Output ItemStack from a Data Stick. + * @param aDataStick - The Data Stick to check. + * @return Output ItemStack contained on the Data Stick. + */ + public static ItemStack getDataStickOutput(ItemStack aDataStick) { + if (doesDataStickHaveOutput(aDataStick)) { + ItemStack aOutput = GT_Utility.loadItem(aDataStick.getTagCompound(), "output"); + return aOutput; + } + return null; + } + + /** + * @param aDataStick - The Data Stick to process. + * @return The stored Recipe Hash String on the Data Stick, will return an invalid Hash if one is not found.

+ * The hash will be guaranteed to pass isValidHash().

+ * Will not return Null. + */ + public static String getHashFromDataStack(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + if (aNBT.hasKey("Data.Recipe.Hash", NBT.TAG_STRING)) { + String hash = aNBT.getString("Data.Recipe.Hash"); + if (isValidHash(hash)) return hash; + } + } + return "Invalid.Recipe.Hash"; + } + + /** + * + * @param aDataStick - The Data Stick to update. + * @param aRecipeHash - The Recipe Hash String to update with. + * @return Did we update the Recipe Hash String on the Data Stick? + */ + public static boolean setRecipeHashOnDataStick(ItemStack aDataStick, String aRecipeHash) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + aNBT.setString("Data.Recipe.Hash", aRecipeHash); + aDataStick.setTagCompound(aNBT); + return true; + } + return false; + } + + /** + * + * @param aDataStick - The Data Stick to update. + * @param aNewRecipe - The New GT_Recipe_AssemblyLine recipe to update it with. + * @return Did we set the new recipe data & Recipe Hash String on the Data Stick? + */ + public static boolean setAssemblyLineRecipeOnDataStick(ItemStack aDataStick, GT_Recipe_AssemblyLine aNewRecipe) { + if (isItemDataStick(aDataStick)) { + String s = aNewRecipe.mOutput.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); + if (s == null) { + s = aNewRecipe.mOutput.getDisplayName(); + } + } + + String aHash = generateRecipeHash(aNewRecipe); + if (GT_Values.D1) { + GT_Recipe_AssemblyLine aOldRecipe = findAssemblyLineRecipeFromDataStick(aDataStick, true).recipe; + GT_FML_LOGGER.info("Updating data stick: " + aDataStick.getDisplayName() + " | Old Recipe Hash: " + + generateRecipeHash(aOldRecipe) + ", New Recipe Hash: " + aHash); + } + + String author = "Assembling Line Recipe Generator"; + String displayName = null; + if (aDataStick.hasTagCompound()) { + NBTTagCompound tag = aDataStick.getTagCompound(); + if (tag.hasKey("author", NBT.TAG_STRING)) { + author = tag.getString("author"); + } + if (tag.hasKey("display", NBT.TAG_COMPOUND)) { + NBTTagCompound displayTag = tag.getCompoundTag("display"); + if (displayTag.hasKey("Name", NBT.TAG_STRING)) displayName = displayTag.getString("Name"); + } + } + + // remove possible old NBTTagCompound + aDataStick.setTagCompound(new NBTTagCompound()); + if (displayName != null) aDataStick.setStackDisplayName(displayName); + if (GT_Values.D1) { + GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data (" + aHash + ")"); + } else { + GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data"); + } + + NBTTagCompound tNBT = aDataStick.getTagCompound(); + if (tNBT == null) { + tNBT = new NBTTagCompound(); + } + + tNBT.setTag("output", aNewRecipe.mOutput.writeToNBT(new NBTTagCompound())); + tNBT.setInteger("time", aNewRecipe.mDuration); + tNBT.setInteger("eu", aNewRecipe.mEUt); + for (int i = 0; i < aNewRecipe.mInputs.length; i++) { + tNBT.setTag("" + i, aNewRecipe.mInputs[i].writeToNBT(new NBTTagCompound())); + } + for (int i = 0; i < aNewRecipe.mOreDictAlt.length; i++) { + if (aNewRecipe.mOreDictAlt[i] != null && aNewRecipe.mOreDictAlt[i].length > 0) { + tNBT.setInteger("a" + i, aNewRecipe.mOreDictAlt[i].length); + for (int j = 0; j < aNewRecipe.mOreDictAlt[i].length; j++) { + tNBT.setTag("a" + i + ":" + j, aNewRecipe.mOreDictAlt[i][j].writeToNBT(new NBTTagCompound())); + } + } + } + for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { + tNBT.setTag("f" + i, aNewRecipe.mFluidInputs[i].writeToNBT(new NBTTagCompound())); + } + tNBT.setString("author", author); + NBTTagList tNBTList = new NBTTagList(); + s = aNewRecipe.mOutput.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); + if (s == null) s = aNewRecipe.mOutput.getDisplayName(); + } + tNBTList.appendTag(new NBTTagString("Construction plan for " + aNewRecipe.mOutput.stackSize + " " + s + + ". Needed EU/t: " + aNewRecipe.mEUt + " Production time: " + (aNewRecipe.mDuration / 20))); + for (int i = 0; i < aNewRecipe.mInputs.length; i++) { + if (aNewRecipe.mOreDictAlt[i] != null) { + int count = 0; + StringBuilder tBuilder = new StringBuilder("Input Bus " + (i + 1) + ": "); + for (ItemStack tStack : aNewRecipe.mOreDictAlt[i]) { + if (tStack != null) { + s = tStack.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(tStack.getDisplayName()); + if (s == null) s = tStack.getDisplayName(); + } + + tBuilder.append(count == 0 ? "" : "\nOr ") + .append(tStack.stackSize) + .append(" ") + .append(s); + count++; + } + } + if (count > 0) tNBTList.appendTag(new NBTTagString(tBuilder.toString())); + } else if (aNewRecipe.mInputs[i] != null) { + s = aNewRecipe.mInputs[i].getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mInputs[i].getDisplayName()); + if (s == null) s = aNewRecipe.mInputs[i].getDisplayName(); + } + tNBTList.appendTag(new NBTTagString( + "Input Bus " + (i + 1) + ": " + aNewRecipe.mInputs[i].stackSize + " " + s)); + } + } + for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { + if (aNewRecipe.mFluidInputs[i] != null) { + s = aNewRecipe.mFluidInputs[i].getLocalizedName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mFluidInputs[i].getLocalizedName()); + if (s == null) s = aNewRecipe.mFluidInputs[i].getLocalizedName(); + } + tNBTList.appendTag(new NBTTagString( + "Input Hatch " + (i + 1) + ": " + aNewRecipe.mFluidInputs[i].amount + "L " + s)); + } + } + tNBT.setTag("pages", tNBTList); + tNBT.setLong("lastUpdate", System.currentTimeMillis()); + aDataStick.setTagCompound(tNBT); + // Set recipe hash + setRecipeHashOnDataStick(aDataStick, aHash); + return true; + } + return false; + } + + public enum LookupResultType { + INVALID_STICK(true), + VALID_STACK_BUT_INVALID_RECIPE(true), + VALID_STACK_AND_VALID_RECIPE(false), + VALID_STACK_AND_VALID_HASH(false); + + private final boolean recipeNull; + private LookupResult singletonResult; + + LookupResultType(boolean recipeNull) { + this.recipeNull = recipeNull; + } + + public LookupResult getResult() { + if (!recipeNull) throw new IllegalArgumentException("This result type require a nonnull recipe"); + if (singletonResult == null) singletonResult = new LookupResult(null, this); + return singletonResult; + } + + public LookupResult getResult(GT_Recipe_AssemblyLine recipe) { + if ((recipe == null) != recipeNull) + throw new IllegalArgumentException("This result type does not allow given input"); + return new LookupResult(recipe, this); + } + } + + public static class LookupResult { + private final GT_Recipe_AssemblyLine recipe; + private final LookupResultType type; + + LookupResult(GT_Recipe_AssemblyLine recipe, LookupResultType type) { + this.recipe = recipe; + this.type = type; + } + + public GT_Recipe_AssemblyLine getRecipe() { + return recipe; + } + + public LookupResultType getType() { + return type; + } + } } diff --git a/src/main/java/gregtech/api/util/GT_Assemblyline_Server.java b/src/main/java/gregtech/api/util/GT_Assemblyline_Server.java index fa838abec1..15d11cda63 100644 --- a/src/main/java/gregtech/api/util/GT_Assemblyline_Server.java +++ b/src/main/java/gregtech/api/util/GT_Assemblyline_Server.java @@ -1,345 +1,415 @@ package gregtech.api.util; -import java.io.File; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - import cpw.mods.fml.common.event.FMLPreInitializationEvent; import gregtech.api.GregTech_API; import gregtech.api.enums.Materials; import gregtech.api.enums.MaterialsBotania; +import java.io.File; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; import net.minecraftforge.common.config.ConfigCategory; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; public class GT_Assemblyline_Server { + public static LinkedHashMap lServerNames = new LinkedHashMap(); + private static LinkedHashMap internal2 = new LinkedHashMap(), + internal3 = new LinkedHashMap(), + internal4 = new LinkedHashMap(); + private static HashMap internal = new HashMap(); - public static LinkedHashMap lServerNames = new LinkedHashMap(); - private static LinkedHashMap internal2 = new LinkedHashMap(), internal3 = new LinkedHashMap(), internal4 = new LinkedHashMap(); - private static HashMap internal = new HashMap(); - - public static void fillMap(FMLPreInitializationEvent aEvent) { + public static void fillMap(FMLPreInitializationEvent aEvent) { - String s = new String(aEvent.getModConfigurationDirectory().getAbsolutePath()); - s = s.substring(0, aEvent.getModConfigurationDirectory().getAbsolutePath().length() - 6); - s = s + "GregTech.lang"; - File f = new File(s); - s = ""; - Configuration conf = new Configuration(f); + String s = new String(aEvent.getModConfigurationDirectory().getAbsolutePath()); + s = s.substring( + 0, aEvent.getModConfigurationDirectory().getAbsolutePath().length() - 6); + s = s + "GregTech.lang"; + File f = new File(s); + s = ""; + Configuration conf = new Configuration(f); - ConfigCategory cat = conf.getCategory("languagefile"); - internal.putAll(cat.getValues()); - for (Map.Entry entry : internal.entrySet()) { - try { - s = entry.getValue().getString().replaceAll("%", ""); + ConfigCategory cat = conf.getCategory("languagefile"); + internal.putAll(cat.getValues()); + for (Map.Entry entry : internal.entrySet()) { + try { + s = entry.getValue().getString().replaceAll("%", ""); - if (entry.getKey().contains("metaitem") && s.contains("material")) - internal2.put(entry.getKey(), s); - else if (entry.getKey().contains("blockmachines") && s.contains("material")) - internal3.put(entry.getKey(), s); - else if ((entry.getKey().contains("blockores") || (entry.getKey().contains("blockmetal") || entry.getKey().contains("blockgem"))) && s.contains("material")) - internal4.put(entry.getKey(), s); - else - lServerNames.put(entry.getKey(), s); - } catch (Exception ignored) { - } - } - for (Map.Entry entry : internal2.entrySet()) { - try { - if (entry.getKey().contains("name")) { - int i = Integer.parseInt(entry.getKey().substring("gt.metaitem.01.".length(), entry.getKey().length() - ".name".length())); - i = i % 1000; - if (GregTech_API.sGeneratedMaterials[i] != null) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", GregTech_API.sGeneratedMaterials[i].toString())); - else - lServerNames.put(entry.getKey(), null); - } - } catch (Exception ignored) { - } - } - for (Map.Entry entry : internal3.entrySet()) { - try { - if (entry.getKey().contains("cable")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.cable.".length(), entry.getKey().length() - ".01.name".length()))); - else if (entry.getKey().contains("gt_frame_")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_frame_".length(), entry.getKey().length() - ".name".length()))); - else if (entry.getKey().contains("gt_pipe_")) { - if ( - !entry.getKey().contains("_huge") && - !entry.getKey().contains("_large") && - !entry.getKey().contains("_nonuple") && - !entry.getKey().contains("_quadruple") && - !entry.getKey().contains("_small") && - !entry.getKey().contains("_tiny") - ) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_pipe_".length(), entry.getKey().length() - ".name".length()))); - else if (entry.getKey().contains("_huge") || entry.getKey().contains("_tiny")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_pipe_".length(), entry.getKey().length() - "_tiny.name".length()))); - else if (entry.getKey().contains("_large") || entry.getKey().contains("_small")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_pipe_".length(), entry.getKey().length() - "_large.name".length()))); - else if (entry.getKey().contains("_nonuple")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_pipe_".length(), entry.getKey().length() - "_nonuple.name".length()))); - else if (entry.getKey().contains("_quadruple")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.gt_pipe_".length(), entry.getKey().length() - "_quadruple.name".length()))); - } else if (entry.getKey().contains("wire")) - lServerNames.put(entry.getKey(), entry.getValue().replace("material", entry.getKey().substring("gt.blockmachines.wire.".length(), entry.getKey().length() - ".01.name".length()))); - else - lServerNames.put(entry.getKey(), entry.getValue()); - } catch (Exception ignored) { - } - } - for (Map.Entry entry : internal4.entrySet()) { - try { - if (entry.getKey().contains("blockores")) { - int i = Integer.parseInt(entry.getKey().substring("gt.blockores.".length(), entry.getKey().length() - ".name".length())); - i