package gregtech.api.util; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.enums.GT_Values.B; import static gregtech.api.enums.GT_Values.D1; import static gregtech.api.enums.GT_Values.DW; import static gregtech.api.enums.GT_Values.E; import static gregtech.api.enums.GT_Values.M; import static gregtech.api.enums.GT_Values.RA; import static gregtech.api.enums.GT_Values.V; import static gregtech.api.enums.GT_Values.W; import static gregtech.api.recipe.RecipeMaps.alloySmelterRecipes; import static gregtech.api.recipe.RecipeMaps.oreWasherRecipes; import static gregtech.api.util.GT_RecipeBuilder.SECONDS; import static gregtech.api.util.GT_RecipeBuilder.TICKS; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.ShapedRecipes; import net.minecraft.item.crafting.ShapelessRecipes; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntityFurnace; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.ShapedOreRecipe; import net.minecraftforge.oredict.ShapelessOreRecipe; import cpw.mods.fml.common.registry.GameRegistry; import gregtech.api.GregTech_API; import gregtech.api.enums.GT_Values; import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; import gregtech.api.enums.OreDictNames; import gregtech.api.enums.OrePrefixes; import gregtech.api.enums.ToolDictNames; import gregtech.api.interfaces.IDamagableItem; import gregtech.api.interfaces.IItemContainer; import gregtech.api.interfaces.internal.IGT_CraftingRecipe; import gregtech.api.items.GT_MetaBase_Item; import gregtech.api.objects.GT_HashSet; import gregtech.api.objects.GT_ItemStack; import gregtech.api.objects.ItemData; import gregtech.api.recipe.RecipeCategories; import gregtech.api.recipe.RecipeMap; import ic2.api.item.IBoxable; import ic2.api.item.IC2Items; import ic2.api.item.IElectricItem; import ic2.api.reactor.IReactorComponent; import ic2.api.recipe.IRecipeInput; import ic2.api.recipe.RecipeInputItemStack; import ic2.api.recipe.RecipeOutput; import ic2.core.item.ItemToolbox; /** * NEVER INCLUDE THIS FILE IN YOUR MOD!!! *

* This is the Interface I use for interacting with other Mods. *

* Due to the many imports, this File can cause compile Problems if not all the APIs are installed */ public class GT_ModHandler { public static final List sSingleNonBlockDamagableRecipeList = new ArrayList<>(1000); private static final Map sIC2ItemMap = new HashMap<>(); // public for bartworks public static final List sAllRecipeList = new ArrayList<>(5000), sBufferRecipeList = new ArrayList<>(1000); private static final List delayedRemovalByOutput = new ArrayList<>(); private static final List delayedRemovalByRecipe = new ArrayList<>(); public static Collection sNativeRecipeClasses = new HashSet<>(), sSpecialRecipeClasses = new HashSet<>(); public static GT_HashSet sNonReplaceableItems = new GT_HashSet<>(); public static Object sBoxableWrapper = new GT_IBoxableWrapper(); public static Collection sBoxableItems = new ArrayList<>(); private static final Map emptyRecipeMap = new HashMap<>(); private static Set recyclerWhitelist; private static Set recyclerBlacklist; private static boolean sBufferCraftingRecipes = true; public static List sSingleNonBlockDamagableRecipeList_list = new ArrayList<>(100); private static final boolean sSingleNonBlockDamagableRecipeList_create = true; private static final ItemStack sMt1 = new ItemStack(Blocks.dirt, 1, 0), sMt2 = new ItemStack(Blocks.dirt, 1, 0); private static final String s_H = "h", s_F = "f", s_I = "I", s_P = "P", s_R = "R"; private static final ItemStack[][] sShapes1 = new ItemStack[][] { { sMt1, null, sMt1, sMt1, sMt1, sMt1, null, sMt1, null }, { sMt1, null, sMt1, sMt1, null, sMt1, sMt1, sMt1, sMt1 }, { null, sMt1, null, sMt1, sMt1, sMt1, sMt1, null, sMt1 }, { sMt1, sMt1, sMt1, sMt1, null, sMt1, null, null, null }, { sMt1, null, sMt1, sMt1, sMt1, sMt1, sMt1, sMt1, sMt1 }, { sMt1, sMt1, sMt1, sMt1, null, sMt1, sMt1, null, sMt1 }, { null, null, null, sMt1, null, sMt1, sMt1, null, sMt1 }, { null, sMt1, null, null, sMt1, null, null, sMt2, null }, { sMt1, sMt1, sMt1, null, sMt2, null, null, sMt2, null }, { null, sMt1, null, null, sMt2, null, null, sMt2, null }, { sMt1, sMt1, null, sMt1, sMt2, null, null, sMt2, null }, { null, sMt1, sMt1, null, sMt2, sMt1, null, sMt2, null }, { sMt1, sMt1, null, null, sMt2, null, null, sMt2, null }, { null, sMt1, sMt1, null, sMt2, null, null, sMt2, null }, { null, sMt1, null, sMt1, null, null, null, sMt1, sMt2 }, { null, sMt1, null, null, null, sMt1, sMt2, sMt1, null }, { null, sMt1, null, sMt1, null, sMt1, null, null, sMt2 }, { null, sMt1, null, sMt1, null, sMt1, sMt2, null, null }, { null, sMt2, null, null, sMt1, null, null, sMt1, null }, { null, sMt2, null, null, sMt2, null, sMt1, sMt1, sMt1 }, { null, sMt2, null, null, sMt2, null, null, sMt1, null }, { null, sMt2, null, sMt1, sMt2, null, sMt1, sMt1, null }, { null, sMt2, null, null, sMt2, sMt1, null, sMt1, sMt1 }, { null, sMt2, null, null, sMt2, null, sMt1, sMt1, null }, { sMt1, null, null, null, sMt2, null, null, null, sMt2 }, { null, null, sMt1, null, sMt2, null, sMt2, null, null }, { sMt1, null, null, null, sMt2, null, null, null, null }, { null, null, sMt1, null, sMt2, null, null, null, null }, { sMt1, sMt2, null, null, null, null, null, null, null }, { sMt2, sMt1, null, null, null, null, null, null, null }, { sMt1, null, null, sMt2, null, null, null, null, null }, { sMt2, null, null, sMt1, null, null, null, null, null }, { sMt1, sMt1, sMt1, sMt1, sMt1, sMt1, null, sMt2, null }, { sMt1, sMt1, null, sMt1, sMt1, sMt2, sMt1, sMt1, null }, { null, sMt1, sMt1, sMt2, sMt1, sMt1, null, sMt1, sMt1 }, { null, sMt2, null, sMt1, sMt1, sMt1, sMt1, sMt1, sMt1 }, { sMt1, sMt1, sMt1, sMt1, sMt2, sMt1, null, sMt2, null }, { sMt1, sMt1, null, sMt1, sMt2, sMt2, sMt1, sMt1, null }, { null, sMt1, sMt1, sMt2, sMt2, sMt1, null, sMt1, sMt1 }, { null, sMt2, null, sMt1, sMt2, sMt1, sMt1, sMt1, sMt1 }, { sMt1, null, null, null, sMt1, null, null, null, null }, { null, sMt1, null, sMt1, null, null, null, null, null }, { sMt1, sMt1, null, sMt2, null, sMt1, sMt2, null, null }, { null, sMt1, sMt1, sMt1, null, sMt2, null, null, sMt2 } }; public static List sSingleNonBlockDamagableRecipeList_validsShapes1 = new ArrayList<>(44); public static boolean sSingleNonBlockDamagableRecipeList_validsShapes1_update = false; public static List sSingleNonBlockDamagableRecipeList_warntOutput = new ArrayList<>(50); public static List sVanillaRecipeList_warntOutput = new ArrayList<>(50); public static final List sSingleNonBlockDamagableRecipeList_verified = new ArrayList<>(1000); public static List sAnySteamFluidIDs = new ArrayList<>(); public static List sSuperHeatedSteamFluidIDs = new ArrayList<>(); static { sNativeRecipeClasses.add(ShapedRecipes.class.getName()); sNativeRecipeClasses.add(ShapedOreRecipe.class.getName()); sNativeRecipeClasses.add(GT_Shaped_Recipe.class.getName()); sNativeRecipeClasses.add(ShapelessRecipes.class.getName()); sNativeRecipeClasses.add(ShapelessOreRecipe.class.getName()); sNativeRecipeClasses.add(GT_Shapeless_Recipe.class.getName()); sNativeRecipeClasses.add(ic2.core.AdvRecipe.class.getName()); sNativeRecipeClasses.add(ic2.core.AdvShapelessRecipe.class.getName()); sNativeRecipeClasses.add("appeng.recipes.game.ShapedRecipe"); sNativeRecipeClasses.add("appeng.recipes.game.ShapelessRecipe"); sNativeRecipeClasses.add("forestry.core.utils.ShapedRecipeCustom"); // Recipe Classes, which should never be removed. sSpecialRecipeClasses.add(net.minecraft.item.crafting.RecipeFireworks.class.getName()); sSpecialRecipeClasses.add(net.minecraft.item.crafting.RecipesArmorDyes.class.getName()); sSpecialRecipeClasses.add(net.minecraft.item.crafting.RecipeBookCloning.class.getName()); sSpecialRecipeClasses.add(net.minecraft.item.crafting.RecipesMapCloning.class.getName()); sSpecialRecipeClasses.add(net.minecraft.item.crafting.RecipesMapExtending.class.getName()); sSpecialRecipeClasses.add("jds.bibliocraft.BiblioSpecialRecipes"); sSpecialRecipeClasses.add("dan200.qcraft.shared.EntangledQBlockRecipe"); sSpecialRecipeClasses.add("dan200.qcraft.shared.EntangledQuantumComputerRecipe"); sSpecialRecipeClasses.add("dan200.qcraft.shared.QBlockRecipe"); sSpecialRecipeClasses.add("appeng.recipes.game.FacadeRecipe"); sSpecialRecipeClasses.add("appeng.recipes.game.DisassembleRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.carts.LocomotivePaintingRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.util.crafting.RotorRepairRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.util.crafting.RoutingTableCopyRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.util.crafting.RoutingTicketCopyRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.util.crafting.TankCartFilterRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.emblems.LocomotiveEmblemRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.emblems.EmblemPostColorRecipe"); sSpecialRecipeClasses.add("mods.railcraft.common.emblems.EmblemPostEmblemRecipe"); sSpecialRecipeClasses.add("mods.immibis.redlogic.interaction.RecipeDyeLumarButton"); sSpecialRecipeClasses.add("thaumcraft.common.items.armor.RecipesRobeArmorDyes"); sSpecialRecipeClasses.add("thaumcraft.common.items.armor.RecipesVoidRobeArmorDyes"); sSpecialRecipeClasses.add("thaumcraft.common.lib.crafting.ShapelessNBTOreRecipe"); sSpecialRecipeClasses.add("twilightforest.item.TFMapCloningRecipe"); sSpecialRecipeClasses.add("forestry.lepidopterology.MatingRecipe"); sSpecialRecipeClasses.add("micdoodle8.mods.galacticraft.planets.asteroids.recipe.CanisterRecipes"); sSpecialRecipeClasses.add("shedar.mods.ic2.nuclearcontrol.StorageArrayRecipe"); } /** * Returns if that Liquid is Water or Distilled Water */ public static boolean isWater(FluidStack aFluid) { if (aFluid == null) return false; return aFluid.isFluidEqual(getWater(1)) || aFluid.isFluidEqual(getDistilledWater(1)); } /** * Returns a Liquid Stack with given amount of Water. */ public static FluidStack getWater(long aAmount) { return FluidRegistry.getFluidStack("water", (int) aAmount); } /** * Returns a Liquid Stack with given amount of distilled Water. */ public static FluidStack getDistilledWater(long aAmount) { FluidStack tFluid = FluidRegistry.getFluidStack("ic2distilledwater", (int) aAmount); if (tFluid == null) tFluid = getWater(aAmount); return tFluid; } /** * Returns if that Liquid is Lava */ public static boolean isLava(FluidStack aFluid) { if (aFluid == null) return false; return aFluid.isFluidEqual(getLava(1)); } /** * Returns a Liquid Stack with given amount of Lava. */ public static FluidStack getLava(long aAmount) { return FluidRegistry.getFluidStack("lava", (int) aAmount); } /** * Returns if that Liquid is Steam */ public static boolean isSteam(FluidStack aFluid) { if (aFluid == null) return false; return aFluid.isFluidEqual(getSteam(1)); } /** * Returns if that Liquid is Any Steam (including other mods) */ public static boolean isAnySteam(FluidStack aFluid) { return (aFluid != null && (isSteam(aFluid) || sAnySteamFluidIDs.contains(aFluid.getFluidID()))); } /** * Returns if that Liquid is Super Heated Steam (including other mods) */ public static boolean isSuperHeatedSteam(FluidStack aFluid) { return (aFluid != null && sSuperHeatedSteamFluidIDs.contains(aFluid.getFluidID())); } /** * Returns a Liquid Stack with given amount of Steam. */ public static FluidStack getSteam(long aAmount) { return FluidRegistry.getFluidStack("steam", (int) aAmount); } /** * Returns if that Liquid is Milk */ public static boolean isMilk(FluidStack aFluid) { if (aFluid == null) return false; return aFluid.isFluidEqual(getMilk(1)); } /** * Returns a Liquid Stack with given amount of Milk. */ public static FluidStack getMilk(long aAmount) { return FluidRegistry.getFluidStack("milk", (int) aAmount); } @Deprecated public static ItemStack getEmptyFuelCan(long aAmount) { return null; } public static ItemStack getEmptyCell(long aAmount) { return ItemList.Cell_Empty.get(aAmount); } public static ItemStack getAirCell(long aAmount) { return ItemList.Cell_Air.get(aAmount); } public static ItemStack getWaterCell(long aAmount) { return ItemList.Cell_Water.get(aAmount); } public static ItemStack getLavaCell(long aAmount) { return ItemList.Cell_Lava.get(aAmount); } /** * @param aValue the Value of this Stack, when burning inside a Furnace (200 = 1 Burn Process = 500 EU, max = 32767 * (that is 81917.5 EU)), limited to Short because the vanilla Furnace otherwise can't handle it * properly, stupid Mojang... */ public static ItemStack setFuelValue(ItemStack aStack, short aValue) { aStack.setTagCompound(GT_Utility.getNBTContainingShort(aStack.getTagCompound(), "GT.ItemFuelValue", aValue)); return aStack; } /** * @return the Value of this Stack, when burning inside a Furnace (200 = 1 Burn Process = 500 EU, max = 32767 (that * is 81917.5 EU)), limited to Short because the vanilla Furnace otherwise can't handle it properly, stupid * Mojang... */ public static int getFuelValue(ItemStack aStack) { return TileEntityFurnace.getItemBurnTime(aStack); } /** * @param aValue Fuel value in EU */ @Deprecated public static ItemStack getFuelCan(int aValue) { return null; } /** * @param aFuelCan the Item you want to check * @return the exact Value in EU the Fuel Can is worth if its even a Fuel Can. */ @Deprecated public static int getFuelCanValue(ItemStack aFuelCan) { return 0; } /** * Gets an Item from IndustrialCraft, and returns a Replacement Item if not possible */ public static ItemStack getIC2Item(String aItem, long aAmount, ItemStack aReplacement) { if (GT_Utility.isStringInvalid(aItem) || !GregTech_API.sPreloadStarted) return null; // if (D1) GT_Log.out.println("Requested the Item '" + aItem + "' from the IC2-API"); if (!sIC2ItemMap.containsKey(aItem)) try { ItemStack tStack = IC2Items.getItem(aItem); sIC2ItemMap.put(aItem, tStack); if (tStack == null && D1) GT_Log.err.println(aItem + " is not found in the IC2 Items!"); } catch (Throwable e) { /* Do nothing */ } return GT_Utility.copyAmount(aAmount, sIC2ItemMap.get(aItem), aReplacement); } /** * Gets an Item from IndustrialCraft, but the Damage Value can be specified, and returns a Replacement Item with the * same Damage if not possible */ public static ItemStack getIC2Item(String aItem, long aAmount, int aMeta, ItemStack aReplacement) { ItemStack rStack = getIC2Item(aItem, aAmount, aReplacement); if (rStack == null) return null; Items.feather.setDamage(rStack, aMeta); return rStack; } /** * Gets an Item from IndustrialCraft, but the Damage Value can be specified */ public static ItemStack getIC2Item(String aItem, long aAmount, int aMeta) { return getIC2Item(aItem, aAmount, aMeta, null); } /** * Gets an Item from IndustrialCraft */ public static ItemStack getIC2Item(String aItem, long aAmount) { return getIC2Item(aItem, aAmount, null); } /** * Gets an Item from the specified mod */ public static ItemStack getModItem(String aModID, String aItem, long aAmount) { return getModItem(aModID, aItem, aAmount, null); } /** * Gets an Item from the specified mod, and returns a Replacement Item if not possible */ public static ItemStack getModItem(String aModID, String aItem, long aAmount, ItemStack aReplacement) { ItemStack result; if (GT_Utility.isStringInvalid(aItem) || !GregTech_API.sPreloadStarted) { result = null; } else { result = GT_Utility .copyAmount(aAmount, GameRegistry.findItemStack(aModID, aItem, (int) aAmount), aReplacement); } if (result == null) { String reason; if (GT_Utility.isStringInvalid(aItem)) { reason = "the name of the item is an invalid string"; } else if (!GregTech_API.sPreloadStarted) { reason = "the GT5U preloading phase has not yet started"; } else { reason = "the item was not found in the game registry"; } String log_message = "getModItem call: object \"" + aItem + "\" with mod id \"" + aModID + "\" has returned null because " + reason; GT_Log.out.println(log_message); new Exception().printStackTrace(GT_Log.out); } return result; } /** * Gets an Item from the specified mod, but the Damage Value can be specified */ public static ItemStack getModItem(String aModID, String aItem, long aAmount, int aMeta) { ItemStack rStack = getModItem(aModID, aItem, aAmount); if (rStack == null) return null; Items.feather.setDamage(rStack, aMeta); return rStack; } /** * Gets an Item from the specified mod, but the Damage Value can be specified, and returns a Replacement Item with * the same Damage if not possible */ public static ItemStack getModItem(String aModID, String aItem, long aAmount, int aMeta, ItemStack aReplacement) { ItemStack rStack = getModItem(aModID, aItem, aAmount, aReplacement); if (rStack == null) return null; Items.feather.setDamage(rStack, aMeta); return rStack; } /** * OUT OF ORDER */ @Deprecated public static boolean getModeKeyDown(EntityPlayer aPlayer) { return false; } /** * OUT OF ORDER */ @Deprecated public static boolean getBoostKeyDown(EntityPlayer aPlayer) { return false; } /** * OUT OF ORDER */ @Deprecated public static boolean getJumpKeyDown(EntityPlayer aPlayer) { return false; } /** * Adds a Valuable Ore to the Miner */ public static boolean addValuableOre(Block aBlock, int aMeta, int aValue) { if (aValue <= 0) return false; try { Class.forName("ic2.core.IC2") .getMethod("addValuableOre", IRecipeInput.class, int.class) .invoke(null, new RecipeInputItemStack(new ItemStack(aBlock, 1, aMeta)), aValue); } catch (Throwable e) { /* Do nothing */ } return true; } /** * Adds a Scrapbox Drop. Fails at April first for the "suddenly Hoes"-Feature of IC2 */ public static boolean addScrapboxDrop(float aChance, ItemStack aOutput) { aOutput = GT_OreDictUnificator.get(true, aOutput); if (aOutput == null || aChance <= 0) return false; aOutput.stackSize = 1; if (GT_Config.troll && !GT_Utility.areStacksEqual(aOutput, new ItemStack(Items.wooden_hoe, 1, 0))) return false; try { GT_Utility.callMethod( GT_Utility.getFieldContent("ic2.api.recipe.Recipes", "scrapboxDrops", true, true), "addDrop", true, false, true, GT_Utility.copyOrNull(aOutput), aChance); GT_Utility.callMethod( GT_Utility.getFieldContent("ic2.api.recipe.Recipes", "scrapboxDrops", true, true), "addRecipe", true, true, false, GT_Utility.copyOrNull(aOutput), aChance); } catch (Throwable e) { /* Do nothing */ } return true; } /** * Adds an Item to the Recycler Blacklist */ public static boolean addToRecyclerBlackList(ItemStack aRecycledStack) { if (aRecycledStack == null) return false; try { ic2.api.recipe.Recipes.recyclerBlacklist.add(new RecipeInputItemStack(aRecycledStack)); } catch (Throwable e) { /* Do nothing */ } return true; } /** * Just simple Furnace smelting. Unbelievable how Minecraft fails at making a simple ItemStack->ItemStack mapping... */ public static boolean addSmeltingRecipe(ItemStack aInput, ItemStack aOutput) { aOutput = GT_OreDictUnificator.get(true, aOutput); if (aInput == null || aOutput == null) return false; FurnaceRecipes.smelting() .func_151394_a(aInput, GT_Utility.copyOrNull(aOutput), 0.0F); return true; } /** * Adds to Furnace AND Alloy Smelter */ public static boolean addSmeltingAndAlloySmeltingRecipe(ItemStack aInput, ItemStack aOutput, boolean hidden) { if (aInput == null || aOutput == null) { return false; } boolean temp = aInput.stackSize == 1 && addSmeltingRecipe(aInput, aOutput); ItemStack input2 = OrePrefixes.ingot.contains(aOutput) ? ItemList.Shape_Mold_Ingot.get(0) : OrePrefixes.block.contains(aOutput) ? ItemList.Shape_Mold_Block.get(0) : OrePrefixes.nugget.contains(aOutput) ? ItemList.Shape_Mold_Nugget.get(0) : null; if (Materials.Graphite.contains(aInput)) { return false; } if ((input2 == null) && ((OrePrefixes.ingot.contains(aInput)) || (OrePrefixes.dust.contains(aInput)) || (OrePrefixes.gem.contains(aInput)))) { return false; } GT_RecipeBuilder recipeBuilder = GT_Values.RA.stdBuilder(); if (input2 == null) { recipeBuilder.itemInputs(aInput); } else { recipeBuilder.itemInputs(aInput, input2); } recipeBuilder.itemOutputs(aOutput) .duration(6 * SECONDS + 10 * TICKS) .eut(3) .recipeCategory(RecipeCategories.alloySmelterRecycling); if (hidden) { recipeBuilder.hidden(); } recipeBuilder.addTo(alloySmelterRecipes); return true; } /** * Adds GT versions of the IC2 recipes from the supplied IC2RecipeList. */ public static void addIC2RecipesToGT(Map aIC2RecipeList, RecipeMap aGTRecipeMap, boolean aAddGTRecipe, boolean aRemoveIC2Recipe, boolean aExcludeGTIC2Items) { Map aRecipesToRemove = new HashMap<>(); for (Entry iRecipeInputRecipeOutputEntry : aIC2RecipeList.entrySet()) { if (iRecipeInputRecipeOutputEntry.getValue().items.isEmpty()) { continue; } for (ItemStack tStack : (iRecipeInputRecipeOutputEntry.getKey()).getInputs()) { if (!GT_Utility.isStackValid(tStack)) { continue; } if (aAddGTRecipe) { try { if (aExcludeGTIC2Items && ((tStack.getUnlocalizedName() .contains("gt.metaitem.01") || tStack.getUnlocalizedName() .contains("gt.blockores") || tStack.getUnlocalizedName() .contains("ic2.itemCrushed") || tStack.getUnlocalizedName() .contains("ic2.itemPurifiedCrushed")))) continue; switch (aGTRecipeMap.unlocalizedName) { case "gt.recipe.macerator", "gt.recipe.extractor", "gt.recipe.compressor" -> GT_Values.RA .stdBuilder() .itemInputs( GT_Utility.copyAmount( iRecipeInputRecipeOutputEntry.getKey() .getAmount(), tStack)) .itemOutputs(iRecipeInputRecipeOutputEntry.getValue().items.toArray(new ItemStack[0])) .duration(15 * SECONDS) .eut(2) .addTo(aGTRecipeMap); case "gt.recipe.thermalcentrifuge" -> GT_Values.RA.stdBuilder() .itemInputs( GT_Utility.copyAmount( iRecipeInputRecipeOutputEntry.getKey() .getAmount(), tStack)) .itemOutputs(iRecipeInputRecipeOutputEntry.getValue().items.toArray(new ItemStack[0])) .duration(25 * SECONDS) .eut(48) .addTo(aGTRecipeMap); } } catch (Exception e) { e.printStackTrace(GT_Log.err); } } if (aRemoveIC2Recipe) { aRecipesToRemove.put(tStack, iRecipeInputRecipeOutputEntry.getValue().items.get(0)); } } } GT_Utility.bulkRemoveSimpleIC2MachineRecipe(aRecipesToRemove, aIC2RecipeList); } public static Map getExtractorRecipeList() { try { return ic2.api.recipe.Recipes.extractor.getRecipes(); } catch (Throwable e) { /* Do nothing */ } return emptyRecipeMap; } public static Map getCompressorRecipeList() { try { return ic2.api.recipe.Recipes.compressor.getRecipes(); } catch (Throwable e) { /* Do nothing */ } return emptyRecipeMap; } public static Map getMaceratorRecipeList() { try { return ic2.api.recipe.Recipes.macerator.getRecipes(); } catch (Throwable e) { /* Do nothing */ } return emptyRecipeMap; } public static Map getThermalCentrifugeRecipeList() { try { return ic2.api.recipe.Recipes.centrifuge.getRecipes(); } catch (Throwable e) { /* Do nothing */ } return emptyRecipeMap; } public static Map getOreWashingRecipeList() { try { return ic2.api.recipe.Recipes.oreWashing.getRecipes(); } catch (Throwable e) { /* Do nothing */ } return emptyRecipeMap; } /** * IC2-OreWasher Recipe. Overloads old Recipes automatically */ @Deprecated public static boolean addOreWasherRecipe(ItemStack aInput, int[] aChances, int aWaterAmount, Object... aOutput) { if (aInput == null || aOutput == null || aOutput.length == 0 || aOutput[0] == null) return false; RA.stdBuilder() .itemInputs(aInput) .itemOutputs((ItemStack) aOutput[0], (ItemStack) aOutput[1], (ItemStack) aOutput[2]) .outputChances(aChances) .fluidInputs(GT_ModHandler.getWater(aWaterAmount)) .duration(25 * SECONDS) .eut(16) .addTo(oreWasherRecipes); RA.stdBuilder() .itemInputs(aInput) .itemOutputs((ItemStack) aOutput[0], (ItemStack) aOutput[1], (ItemStack) aOutput[2]) .outputChances(aChances) .fluidInputs(GT_ModHandler.getDistilledWater(aWaterAmount / 5)) .duration(15 * SECONDS) .eut(16) .addTo(oreWasherRecipes); return true; } public static void stopBufferingCraftingRecipes() { sBufferCraftingRecipes = false; bulkRemoveRecipeByOutput(delayedRemovalByOutput); bulkRemoveByRecipe(delayedRemovalByRecipe); sBufferRecipeList.forEach(GameRegistry::addRecipe); delayedRemovalByOutput.clear(); delayedRemovalByRecipe.clear(); sBufferRecipeList.clear(); } /** * Shapeless Crafting Recipes. Deletes conflicting Recipes too. */ public static boolean addCraftingRecipe(ItemStack aResult, Enchantment[] aEnchantmentsAdded, int[] aEnchantmentLevelsAdded, Object[] aRecipe) { return addCraftingRecipe( aResult, aEnchantmentsAdded, aEnchantmentLevelsAdded, false, true, false, false, false, false, false, false, false, false, false, false, true, aRecipe); } /** * Regular Crafting Recipes. Deletes conflicting Recipes too. *

* You can insert instances of IItemContainer into the Recipe Input Array directly without having to call "get(1)" * on them. *

* Enums are automatically getting their "name()"-Method called in order to deliver an OreDict String. *

* Lowercase Letters are reserved for Tools. They are as follows: *

* 'b' ToolDictNames.craftingToolBlade 'c' ToolDictNames.craftingToolCrowbar, 'd' * ToolDictNames.craftingToolScrewdriver, 'f' ToolDictNames.craftingToolFile, 'h' * ToolDictNames.craftingToolHardHammer, 'i' ToolDictNames.craftingToolSolderingIron, 'j' * ToolDictNames.craftingToolSolderingMetal, 'k' ToolDictNames.craftingToolKnive 'm' * ToolDictNames.craftingToolMortar, 'p' ToolDictNames.craftingToolDrawplate, 'r' * ToolDictNames.craftingToolSoftHammer, 's' ToolDictNames.craftingToolSaw, 'w' ToolDictNames.craftingToolWrench, * 'x' ToolDictNames.craftingToolWireCutter, */ public static boolean addCraftingRecipe(ItemStack aResult, Object[] aRecipe) { return addCraftingRecipe(aResult, 0, aRecipe); } /** * Regular Crafting Recipes. Deletes conflicting Recipes too. *

* You can insert instances of IItemContainer into the Recipe Input Array directly without having to call "get(1)" * on them. *

* Enums are automatically getting their "name()"-Method called in order to deliver an OreDict String. *

* Lowercase Letters are reserved for Tools. They are as follows: *

* 'b' ToolDictNames.craftingToolBlade 'c' ToolDictNames.craftingToolCrowbar, 'd' * ToolDictNames.craftingToolScrewdriver, 'f' ToolDictNames.craftingToolFile, 'h' * ToolDictNames.craftingToolHardHammer, 'i' ToolDictNames.craftingToolSolderingIron, 'j' * ToolDictNames.craftingToolSolderingMetal, 'k' ToolDictNames.craftingToolKnive 'm' * ToolDictNames.craftingToolMortar, 'p' ToolDictNames.craftingToolDrawplate, 'r' * ToolDictNames.craftingToolSoftHammer, 's' ToolDictNames.craftingToolSaw, 'w' ToolDictNames.craftingToolWrench, * 'x' ToolDictNames.craftingToolWireCutter, */ public static boolean addCraftingRecipe(ItemStack aResult, long aBitMask, Object[] aRecipe) { return addCraftingRecipe( aResult, new Enchantment[0], new int[0], (aBitMask & RecipeBits.MIRRORED) != 0, (aBitMask & RecipeBits.BUFFERED) != 0, (aBitMask & RecipeBits.KEEPNBT) != 0, (aBitMask & RecipeBits.DISMANTLEABLE) != 0, (aBitMask & RecipeBits.NOT_REMOVABLE) == 0, (aBitMask & RecipeBits.REVERSIBLE) != 0, (aBitMask & RecipeBits.DELETE_ALL_OTHER_RECIPES) != 0, (aBitMask & RecipeBits.DELETE_ALL_OTHER_RECIPES_IF_SAME_NBT) != 0, (aBitMask & RecipeBits.DELETE_ALL_OTHER_SHAPED_RECIPES) != 0, (aBitMask & RecipeBits.DELETE_ALL_OTHER_NATIVE_RECIPES) != 0, (aBitMask & RecipeBits.DO_NOT_CHECK_FOR_COLLISIONS) == 0, (aBitMask & RecipeBits.ONLY_ADD_IF_THERE_IS_ANOTHER_RECIPE_FOR_IT) != 0, (aBitMask & RecipeBits.ONLY_ADD_IF_RESULT_IS_NOT_NULL) != 0, aRecipe); } /** * Internal realisation of the Crafting Recipe adding Process. */ private static boolean addCraftingRecipe(ItemStack aResult, Enchantment[] aEnchantmentsAdded, int[] aEnchantmentLevelsAdded, boolean aMirrored, boolean aBuffered, boolean aKeepNBT, boolean aDismantleable, boolean aRemovable, boolean aReversible, boolean aRemoveAllOthersWithSameOutput, boolean aRemoveAllOthersWithSameOutputIfTheyHaveSameNBT, boolean aRemoveAllOtherShapedsWithSameOutput, boolean aRemoveAllOtherNativeRecipes, boolean aCheckForCollisions, boolean aOnlyAddIfThereIsAnyRecipeOutputtingThis, boolean aOnlyAddIfResultIsNotNull, Object[] aRecipe) { aResult = GT_OreDictUnificator.get(true, aResult); if (aOnlyAddIfResultIsNotNull && aResult == null) return false; if (aResult != null && Items.feather.getDamage(aResult) == W) Items.feather.setDamage(aResult, 0); if (aRecipe == null || aRecipe.length == 0) return false; // The renamed variable clarifies what's happening // noinspection UnnecessaryLocalVariable boolean tDoWeCareIfThereWasARecipe = aOnlyAddIfThereIsAnyRecipeOutputtingThis; boolean tThereWasARecipe = false; for (byte i = 0; i < aRecipe.length; i++) { if (aRecipe[i] instanceof IItemContainer) aRecipe[i] = ((IItemContainer) aRecipe[i]).get(1); else if (aRecipe[i] instanceof Enum) aRecipe[i] = ((Enum) aRecipe[i]).name(); else if (!(aRecipe[i] == null || aRecipe[i] instanceof ItemStack || aRecipe[i] instanceof ItemData || aRecipe[i] instanceof String || aRecipe[i] instanceof Character)) aRecipe[i] = aRecipe[i].toString(); } try { StringBuilder shape = new StringBuilder(E); int idx = 0; if (aRecipe[idx] instanceof Boolean) { throw new IllegalArgumentException(); } ArrayList tRecipeList = new ArrayList<>(Arrays.asList(aRecipe)); while (aRecipe[idx] instanceof String) { StringBuilder s = new StringBuilder((String) aRecipe[idx++]); shape.append(s); while (s.length() < 3) s.append(" "); if (s.length() > 3) throw new IllegalArgumentException(); for (char c : s.toString() .toCharArray()) { switch (c) { case 'b' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolBlade.name()); } case 'c' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolCrowbar.name()); } case 'd' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolScrewdriver.name()); } case 'f' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolFile.name()); } case 'h' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolHardHammer.name()); } case 'i' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolSolderingIron.name()); } case 'j' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolSolderingMetal.name()); } case 'k' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolKnife.name()); } case 'm' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolMortar.name()); } case 'p' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolDrawplate.name()); } case 'r' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolSoftHammer.name()); } case 's' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolSaw.name()); } case 'w' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolWrench.name()); } case 'x' -> { tRecipeList.add(c); tRecipeList.add(ToolDictNames.craftingToolWireCutter.name()); } } } } aRecipe = tRecipeList.toArray(); if (aRecipe[idx] instanceof Boolean) { idx++; } Map tItemStackMap = new HashMap<>(); Map tItemDataMap = new HashMap<>(); tItemStackMap.put(' ', null); boolean tRemoveRecipe = true; for (; idx < aRecipe.length; idx += 2) { if (aRecipe[idx] == null || aRecipe[idx + 1] == null) { if (D1) { GT_Log.err.println( "WARNING: Missing Item for shaped Recipe: " + (aResult == null ? "null" : aResult.getDisplayName())); for (Object tContent : aRecipe) GT_Log.err.println(tContent); } return false; } Character chr = (Character) aRecipe[idx]; Object in = aRecipe[idx + 1]; if (in instanceof ItemStack is) { tItemStackMap.put(chr, GT_Utility.copyOrNull(is)); tItemDataMap.put(chr, GT_OreDictUnificator.getItemData(is)); } else if (in instanceof ItemData) { String tString = in.toString(); switch (tString) { case "plankWood" -> tItemDataMap.put(chr, new ItemData(Materials.Wood, M)); case "stoneNetherrack" -> tItemDataMap.put(chr, new ItemData(Materials.Netherrack, M)); case "stoneObsidian" -> tItemDataMap.put(chr, new ItemData(Materials.Obsidian, M)); case "stoneEndstone" -> tItemDataMap.put(chr, new ItemData(Materials.Endstone, M)); default -> tItemDataMap.put(chr, (ItemData) in); } ItemStack tStack = GT_OreDictUnificator.getFirstOre(in, 1); if (tStack == null) tRemoveRecipe = false; else tItemStackMap.put(chr, tStack); in = aRecipe[idx + 1] = in.toString(); } else if (in instanceof String) { if (in.equals(OreDictNames.craftingChest.toString())) tItemDataMap.put(chr, new ItemData(Materials.Wood, M * 8)); else if (in.equals(OreDictNames.craftingBook.toString())) tItemDataMap.put(chr, new ItemData(Materials.Paper, M * 3)); else if (in.equals(OreDictNames.craftingPiston.toString())) tItemDataMap.put(chr, new ItemData(Materials.Stone, M * 4, Materials.Wood, M * 3)); else if (in.equals(OreDictNames.craftingFurnace.toString())) tItemDataMap.put(chr, new ItemData(Materials.Stone, M * 8)); else if (in.equals(OreDictNames.craftingIndustrialDiamond.toString())) tItemDataMap.put(chr, new ItemData(Materials.Diamond, M)); else if (in.equals(OreDictNames.craftingAnvil.toString())) tItemDataMap.put(chr, new ItemData(Materials.Iron, M * 10)); ItemStack tStack = GT_OreDictUnificator.getFirstOre(in, 1); if (tStack == null) tRemoveRecipe = false; else tItemStackMap.put(chr, tStack); } else { throw new IllegalArgumentException(); } } if (aReversible && aResult != null) { ItemData[] tData = new ItemData[9]; int x = -1; for (char chr : shape.toString() .toCharArray()) tData[++x] = tItemDataMap.get(chr); if (GT_Utility.arrayContainsNonNull(tData)) GT_OreDictUnificator.addItemData(aResult, new ItemData(tData)); } if (aCheckForCollisions && tRemoveRecipe) { ItemStack[] tRecipe = new ItemStack[9]; int x = -1; for (char chr : shape.toString() .toCharArray()) { tRecipe[++x] = tItemStackMap.get(chr); if (tRecipe[x] != null && Items.feather.getDamage(tRecipe[x]) == W) Items.feather.setDamage(tRecipe[x], 0); } if (tDoWeCareIfThereWasARecipe || !aBuffered) tThereWasARecipe = removeRecipe(tRecipe) != null; else removeRecipeDelayed(tRecipe); } } catch (Throwable e) { e.printStackTrace(GT_Log.err); } if (aResult == null || aResult.stackSize <= 0) return false; if (aRemoveAllOthersWithSameOutput || aRemoveAllOthersWithSameOutputIfTheyHaveSameNBT || aRemoveAllOtherShapedsWithSameOutput || aRemoveAllOtherNativeRecipes) { if (tDoWeCareIfThereWasARecipe || !aBuffered) tThereWasARecipe = removeRecipeByOutput( aResult, !aRemoveAllOthersWithSameOutputIfTheyHaveSameNBT, aRemoveAllOtherShapedsWithSameOutput, aRemoveAllOtherNativeRecipes) || tThereWasARecipe; else removeRecipeByOutputDelayed(aResult); } if (aOnlyAddIfThereIsAnyRecipeOutputtingThis && !tDoWeCareIfThereWasARecipe && !tThereWasARecipe) { ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); int tList_sS = tList.size(); for (int i = 0; i < tList_sS && !tThereWasARecipe; i++) { IRecipe tRecipe = tList.get(i); if (sSpecialRecipeClasses.contains( tRecipe.getClass() .getName())) continue; if (GT_Utility.areStacksEqual(GT_OreDictUnificator.get(tRecipe.getRecipeOutput()), aResult, true)) { tList.remove(i--); tList_sS = tList.size(); tThereWasARecipe = true; } } } if (Items.feather.getDamage(aResult) == W || Items.feather.getDamage(aResult) < 0) Items.feather.setDamage(aResult, 0); GT_Utility.updateItemStack(aResult); if (tThereWasARecipe || !aOnlyAddIfThereIsAnyRecipeOutputtingThis) { if (sBufferCraftingRecipes && aBuffered) sBufferRecipeList.add( new GT_Shaped_Recipe( GT_Utility.copyOrNull(aResult), aDismantleable, aRemovable, aKeepNBT, aEnchantmentsAdded, aEnchantmentLevelsAdded, aRecipe).setMirrored(aMirrored)); else GameRegistry.addRecipe( new GT_Shaped_Recipe( GT_Utility.copyOrNull(aResult), aDismantleable, aRemovable, aKeepNBT, aEnchantmentsAdded, aEnchantmentLevelsAdded, aRecipe).setMirrored(aMirrored)); } return true; } /** * Shapeless Crafting Recipes. Deletes conflicting Recipes too. */ public static boolean addShapelessEnchantingRecipe(ItemStack aResult, Enchantment[] aEnchantmentsAdded, int[] aEnchantmentLevelsAdded, Object[] aRecipe) { return addShapelessCraftingRecipe( aResult, aEnchantmentsAdded, aEnchantmentLevelsAdded, true, false, false, false, aRecipe); } /** * Shapeless Crafting Recipes. Deletes conflicting Recipes too. */ public static boolean addShapelessCraftingRecipe(ItemStack aResult, Object[] aRecipe) { return addShapelessCraftingRecipe( aResult, RecipeBits.DO_NOT_CHECK_FOR_COLLISIONS | RecipeBits.BUFFERED, aRecipe); } /** * Shapeless Crafting Recipes. Deletes conflicting Recipes too. */ public static boolean addShapelessCraftingRecipe(ItemStack aResult, long aBitMask, Object[] aRecipe) { return addShapelessCraftingRecipe( aResult, new Enchantment[0], new int[0], (aBitMask & RecipeBits.BUFFERED) != 0, (aBitMask & RecipeBits.KEEPNBT) != 0, (aBitMask & RecipeBits.DISMANTLEABLE) != 0, (aBitMask & RecipeBits.NOT_REMOVABLE) == 0, aRecipe); } /** * Shapeless Crafting Recipes. Deletes conflicting Recipes too. */ private static boolean addShapelessCraftingRecipe(ItemStack aResult, Enchantment[] aEnchantmentsAdded, int[] aEnchantmentLevelsAdded, boolean aBuffered, boolean aKeepNBT, boolean aDismantleable, boolean aRemovable, Object[] aRecipe) { aResult = GT_OreDictUnificator.get(true, aResult); if (aRecipe == null || aRecipe.length == 0) return false; for (byte i = 0; i < aRecipe.length; i++) { if (aRecipe[i] instanceof IItemContainer) aRecipe[i] = ((IItemContainer) aRecipe[i]).get(1); else if (aRecipe[i] instanceof Enum) aRecipe[i] = ((Enum) aRecipe[i]).name(); else if (!(aRecipe[i] == null || aRecipe[i] instanceof ItemStack || aRecipe[i] instanceof String || aRecipe[i] instanceof Character)) aRecipe[i] = aRecipe[i].toString(); } try { ItemStack[] tRecipe = new ItemStack[9]; int i = 0; for (Object tObject : aRecipe) { if (tObject == null) { if (D1) GT_Log.err.println( "WARNING: Missing Item for shapeless Recipe: " + (aResult == null ? "null" : aResult.getDisplayName())); for (Object tContent : aRecipe) GT_Log.err.println(tContent); return false; } if (tObject instanceof ItemStack) { tRecipe[i] = (ItemStack) tObject; } else if (tObject instanceof String) { tRecipe[i] = GT_OreDictUnificator.getFirstOre(tObject, 1); if (tRecipe[i] == null) break; } i++; } if (sBufferCraftingRecipes && aBuffered) removeRecipeDelayed(tRecipe); else removeRecipe(tRecipe); } catch (Throwable e) { e.printStackTrace(GT_Log.err); } if (aResult == null || aResult.stackSize <= 0) return false; if (Items.feather.getDamage(aResult) == W || Items.feather.getDamage(aResult) < 0) Items.feather.setDamage(aResult, 0); GT_Utility.updateItemStack(aResult); if (sBufferCraftingRecipes && aBuffered) sBufferRecipeList.add( new GT_Shapeless_Recipe( GT_Utility.copyOrNull(aResult), aDismantleable, aRemovable, aKeepNBT, aEnchantmentsAdded, aEnchantmentLevelsAdded, aRecipe)); else GameRegistry.addRecipe( new GT_Shapeless_Recipe( GT_Utility.copyOrNull(aResult), aDismantleable, aRemovable, aKeepNBT, aEnchantmentsAdded, aEnchantmentLevelsAdded, aRecipe)); return true; } /** * Removes a Smelting Recipe */ public static boolean removeFurnaceSmelting(ItemStack aInput) { if (aInput != null) { for (ItemStack tInput : FurnaceRecipes.smelting() .getSmeltingList() .keySet()) { if (GT_Utility.isStackValid(tInput) && GT_Utility.areStacksEqual(aInput, tInput, true)) { FurnaceRecipes.smelting() .getSmeltingList() .remove(tInput); return true; } } } return false; } /** * Removes all matching Smelting Recipes by output */ public static boolean removeFurnaceSmeltingByOutput(ItemStack aOutput) { if (aOutput != null) { return FurnaceRecipes.smelting() .getSmeltingList() .values() .removeIf( tOutput -> GT_Utility.isStackValid(tOutput) && GT_Utility.areStacksEqual(aOutput, tOutput, true)); } return false; } /** * Removes a Crafting Recipe and gives you the former output of it. * * @param aRecipe The content of the Crafting Grid as ItemStackArray with length 9 * @return the output of the old Recipe or null if there was nothing. */ public static ItemStack removeRecipe(ItemStack... aRecipe) { if (aRecipe == null) return null; if (Arrays.stream(aRecipe) .noneMatch(Objects::nonNull)) return null; ItemStack rReturn = null; InventoryCrafting aCrafting = new InventoryCrafting(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { return false; } }, 3, 3); for (int i = 0; i < aRecipe.length && i < 9; i++) aCrafting.setInventorySlotContents(i, aRecipe[i]); ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); int tList_sS = tList.size(); try { for (int i = 0; i < tList_sS; i++) { for (; i < tList_sS; i++) { if ((!(tList.get(i) instanceof IGT_CraftingRecipe) || ((IGT_CraftingRecipe) tList.get(i)).isRemovable()) && tList.get(i) .matches(aCrafting, DW)) { rReturn = tList.get(i) .getCraftingResult(aCrafting); if (rReturn != null) tList.remove(i--); tList_sS = tList.size(); } } } } catch (Throwable e) { e.printStackTrace(GT_Log.err); } return rReturn; } public static void removeRecipeDelayed(ItemStack... aRecipe) { if (!sBufferCraftingRecipes) { removeRecipe(aRecipe); return; } if (aRecipe == null) return; if (Arrays.stream(aRecipe) .noneMatch(Objects::nonNull)) return; InventoryCrafting aCrafting = new InventoryCrafting(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { return false; } }, 3, 3); for (int i = 0; i < aRecipe.length && i < 9; i++) aCrafting.setInventorySlotContents(i, aRecipe[i]); delayedRemovalByRecipe.add(aCrafting); } public static void bulkRemoveByRecipe(List toRemove) { ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); GT_FML_LOGGER.info("BulkRemoveByRecipe: tList: " + tList.size() + " toRemove: " + toRemove.size()); Set tListToRemove = tList.parallelStream() .filter(tRecipe -> { if ((tRecipe instanceof IGT_CraftingRecipe) && !((IGT_CraftingRecipe) tRecipe).isRemovable()) return false; return toRemove.stream() .anyMatch(aCrafting -> tRecipe.matches(aCrafting, DW)); }) .collect(Collectors.toSet()); tList.removeIf(tListToRemove::contains); } public static boolean removeRecipeByOutputDelayed(ItemStack aOutput) { if (sBufferCraftingRecipes) return delayedRemovalByOutput.add(aOutput); else return removeRecipeByOutput(aOutput); } public static boolean removeRecipeByOutputDelayed(ItemStack aOutput, boolean aIgnoreNBT, boolean aNotRemoveShapelessRecipes, boolean aOnlyRemoveNativeHandlers) { if (sBufferCraftingRecipes && (aIgnoreNBT && !aNotRemoveShapelessRecipes && !aOnlyRemoveNativeHandlers)) // Too lazy to handle deferred versions of the parameters that aren't used very often return delayedRemovalByOutput.add(aOutput); else return removeRecipeByOutput(aOutput, aIgnoreNBT, aNotRemoveShapelessRecipes, aOnlyRemoveNativeHandlers); } public static boolean removeRecipeByOutput(ItemStack aOutput) { return removeRecipeByOutput(aOutput, true, false, false); } /** * Removes a Crafting Recipe. * * @param aOutput The output of the Recipe. * @return if it has removed at least one Recipe. */ public static boolean removeRecipeByOutput(ItemStack aOutput, boolean aIgnoreNBT, boolean aNotRemoveShapelessRecipes, boolean aOnlyRemoveNativeHandlers) { if (aOutput == null) return false; boolean rReturn = false; final ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); aOutput = GT_OreDictUnificator.get(aOutput); int tList_sS = tList.size(); for (int i = 0; i < tList_sS; i++) { final IRecipe tRecipe = tList.get(i); if (aNotRemoveShapelessRecipes && (tRecipe instanceof ShapelessRecipes || tRecipe instanceof ShapelessOreRecipe)) continue; if (aOnlyRemoveNativeHandlers) { if (!sNativeRecipeClasses.contains( tRecipe.getClass() .getName())) continue; } else { if (sSpecialRecipeClasses.contains( tRecipe.getClass() .getName())) continue; } ItemStack tStack = tRecipe.getRecipeOutput(); if ((!(tRecipe instanceof IGT_CraftingRecipe) || ((IGT_CraftingRecipe) tRecipe).isRemovable()) && GT_Utility.areStacksEqual(GT_OreDictUnificator.get(tStack), aOutput, aIgnoreNBT)) { tList.remove(i--); tList_sS = tList.size(); rReturn = true; } } return rReturn; } public static boolean bulkRemoveRecipeByOutput(List toRemove) { ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); Set setToRemove = toRemove.parallelStream() .map(GT_OreDictUnificator::get_nocopy) .collect(Collectors.toSet()); GT_FML_LOGGER.info("BulkRemoveRecipeByOutput: tList: " + tList.size() + " setToRemove: " + setToRemove.size()); Set tListToRemove = tList.parallelStream() .filter(tRecipe -> { if ((tRecipe instanceof IGT_CraftingRecipe) && !((IGT_CraftingRecipe) tRecipe).isRemovable()) return false; if (sSpecialRecipeClasses.contains( tRecipe.getClass() .getName())) return false; final ItemStack tStack = GT_OreDictUnificator.get_nocopy(tRecipe.getRecipeOutput()); return setToRemove.stream() .anyMatch(aOutput -> GT_Utility.areStacksEqual(tStack, aOutput, true)); }) .collect(Collectors.toSet()); tList.removeIf(tListToRemove::contains); return true; } /** * Checks all Crafting Handlers for Recipe Output Used for the Autocrafting Table */ public static ItemStack getAllRecipeOutput(World aWorld, ItemStack... aRecipe) { if (aRecipe == null || aRecipe.length == 0) return null; if (aWorld == null) aWorld = DW; boolean temp = false; for (ItemStack itemStack : aRecipe) { if (itemStack != null) { temp = true; break; } } if (!temp) return null; InventoryCrafting aCrafting = new InventoryCrafting(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { return false; } }, 3, 3); for (int i = 0; i < 9 && i < aRecipe.length; i++) aCrafting.setInventorySlotContents(i, aRecipe[i]); List tList = CraftingManager.getInstance() .getRecipeList(); synchronized (sAllRecipeList) { if (sAllRecipeList.size() != tList.size()) { sAllRecipeList.clear(); sAllRecipeList.addAll(tList); } for (int i = 0, j = sAllRecipeList.size(); i < j; i++) { IRecipe tRecipe = sAllRecipeList.get(i); if (tRecipe.matches(aCrafting, aWorld)) { if (i > 10) { sAllRecipeList.remove(i); sAllRecipeList.add(i - 10, tRecipe); } return tRecipe.getCraftingResult(aCrafting); } } } int tIndex = 0; ItemStack tStack1 = null, tStack2 = null; for (int i = 0, j = aCrafting.getSizeInventory(); i < j; i++) { ItemStack tStack = aCrafting.getStackInSlot(i); if (tStack != null) { if (tIndex == 0) tStack1 = tStack; if (tIndex == 1) tStack2 = tStack; tIndex++; } } if (tIndex == 2 && tStack2 != null) { if (tStack1.getItem() == tStack2.getItem() && tStack1.stackSize == 1 && tStack2.stackSize == 1 && tStack1.getItem() .isRepairable()) { int tNewDamage = tStack1.getMaxDamage() + tStack1.getItemDamage() - tStack2.getItemDamage() + tStack1.getMaxDamage() / 20; return new ItemStack(tStack1.getItem(), 1, Math.max(tNewDamage, 0)); } } return null; } /** * Gives you a copy of the Output from a Crafting Recipe Used for Recipe Detection. */ public static ItemStack getRecipeOutput(ItemStack... aRecipe) { return getRecipeOutput(false, true, aRecipe); } public static ItemStack getRecipeOutputNoOreDict(ItemStack... aRecipe) { return getRecipeOutput(false, false, aRecipe); } public static ItemStack getRecipeOutput(boolean aUncopiedStack, ItemStack... aRecipe) { return getRecipeOutput(aUncopiedStack, true, aRecipe); } /** * Gives you a copy of the Output from a Crafting Recipe Used for Recipe Detection. */ public static ItemStack getRecipeOutput(boolean aUncopiedStack, boolean allowOreDict, ItemStack... aRecipe) { if (aRecipe == null || Arrays.stream(aRecipe) .noneMatch(Objects::nonNull)) return null; InventoryCrafting aCrafting = new InventoryCrafting(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { return false; } }, 3, 3); for (int i = 0; i < 9 && i < aRecipe.length; i++) aCrafting.setInventorySlotContents(i, aRecipe[i]); ArrayList tList = (ArrayList) CraftingManager.getInstance() .getRecipeList(); boolean found = false; for (IRecipe iRecipe : tList) { found = false; if (!allowOreDict && iRecipe instanceof ShapedOreRecipe) continue; try { found = iRecipe.matches(aCrafting, DW); } catch (Throwable e) { e.printStackTrace(GT_Log.err); } if (found) { ItemStack tOutput = aUncopiedStack ? iRecipe.getRecipeOutput() : iRecipe.getCraftingResult(aCrafting); if (tOutput == null || tOutput.stackSize <= 0) { // Seriously, who would ever do that shit? if (!GregTech_API.sPostloadFinished) throw new GT_ItsNotMyFaultException( "Seems another Mod added a Crafting Recipe with null Output. Tell the Developer of said Mod to fix that."); } else { if (aUncopiedStack) return tOutput; return GT_Utility.copyOrNull(tOutput); } } } return null; } /** * Gives you a list of the Outputs from a Crafting Recipe If you have multiple Mods, which add Bronze Armor for * example This also removes old Recipes from the List. */ public static List getVanillyToolRecipeOutputs(ItemStack... aRecipe) { if (!GregTech_API.sPostloadStarted || GregTech_API.sPostloadFinished) sSingleNonBlockDamagableRecipeList.clear(); if (sSingleNonBlockDamagableRecipeList.isEmpty()) { for (IRecipe tRecipe : CraftingManager.getInstance() .getRecipeList()) { ItemStack tStack = tRecipe.getRecipeOutput(); if (GT_Utility.isStackValid(tStack) && tStack.getMaxStackSize() == 1 && tStack.getMaxDamage() > 0 && !(tStack.getItem() instanceof ItemBlock) && !(tStack.getItem() instanceof IReactorComponent) && !isElectricItem(tStack) && !GT_Utility.isStackInList(tStack, sNonReplaceableItems)) { if (!(tRecipe instanceof ShapelessRecipes || tRecipe instanceof ShapelessOreRecipe)) { if (tRecipe instanceof ShapedOreRecipe) { boolean temp = true; for (Object tObject : ((ShapedOreRecipe) tRecipe).getInput()) if (tObject != null) { if (tObject instanceof ItemStack && (((ItemStack) tObject).getItem() == null || ((ItemStack) tObject).getMaxStackSize() < 2 || ((ItemStack) tObject).getMaxDamage() > 0 || ((ItemStack) tObject).getItem() instanceof ItemBlock)) { temp = false; break; } if (tObject instanceof List && ((List) tObject).isEmpty()) { temp = false; break; } } if (temp) sSingleNonBlockDamagableRecipeList.add(tRecipe); } else if (tRecipe instanceof ShapedRecipes) { boolean temp = true; for (ItemStack tObject : ((ShapedRecipes) tRecipe).recipeItems) { if (tObject != null && (tObject.getItem() == null || tObject.getMaxStackSize() < 2 || tObject.getMaxDamage() > 0 || tObject.getItem() instanceof ItemBlock)) { temp = false; break; } } if (temp) sSingleNonBlockDamagableRecipeList.add(tRecipe); } else { sSingleNonBlockDamagableRecipeList.add(tRecipe); } } } } GT_Log.out.println( "GT_Mod: Created a List of Tool Recipes containing " + sSingleNonBlockDamagableRecipeList.size() + " Recipes for recycling." + (sSingleNonBlockDamagableRecipeList.size() > 1024 ? " Scanning all these Recipes is the reason for the startup Lag you receive right now." : E)); } List rList = getRecipeOutputs(sSingleNonBlockDamagableRecipeList, true, aRecipe); if (!GregTech_API.sPostloadStarted || GregTech_API.sPostloadFinished) sSingleNonBlockDamagableRecipeList.clear(); return rList; } /** * Gives you a list of the Outputs from a Crafting Recipe If you have multiple Mods, which add Bronze Armor for * example */ public static List getRecipeOutputs(ItemStack... aRecipe) { return getRecipeOutputs( CraftingManager.getInstance() .getRecipeList(), false, aRecipe); } private static List bufferedRecipes = null; /** * Gives you a list of the Outputs from a Crafting Recipe If you have multiple Mods, which add Bronze Armor for * example Buffers a List which only has armor-alike crafting in it */ public static List getRecipeOutputsBuffered(ItemStack... aRecipe) { if (bufferedRecipes == null) bufferedRecipes = CraftingManager.getInstance() .getRecipeList() .stream() .filter( tRecipe -> !(tRecipe instanceof ShapelessRecipes) && !(tRecipe instanceof ShapelessOreRecipe) && !(tRecipe instanceof IGT_CraftingRecipe)) .filter(tRecipe -> { try { ItemStack tOutput = tRecipe.getRecipeOutput(); if (tOutput.stackSize == 1 && tOutput.getMaxDamage() > 0 && tOutput.getMaxStackSize() == 1) { return true; } } catch (Exception ignored) {} return false; }) .collect(Collectors.toList()); return getRecipeOutputs(bufferedRecipes, false, aRecipe); } /** * Gives you a list of the Outputs from a Crafting Recipe If you have multiple Mods, which add Bronze Armor for * example */ public static List getRecipeOutputs(List aList, boolean aDeleteFromList, ItemStack... aRecipe) { List rList = new ArrayList<>(); if (aRecipe == null || Arrays.stream(aRecipe) .noneMatch(Objects::nonNull)) return rList; InventoryCrafting aCrafting = new InventoryCrafting(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { return false; } }, 3, 3); for (int i = 0; i < 9 && i < aRecipe.length; i++) aCrafting.setInventorySlotContents(i, aRecipe[i]); if (!aDeleteFromList) { HashSet stacks = new HashSet<>(); aList.stream() .filter(tRecipe -> { if (tRecipe instanceof ShapelessRecipes || tRecipe instanceof ShapelessOreRecipe || tRecipe instanceof IGT_CraftingRecipe) return false; try { return tRecipe.matches(aCrafting, DW); } catch (Throwable e) { e.printStackTrace(GT_Log.err); return false; } }) .forEach(tRecipe -> stacks.add(tRecipe.getCraftingResult(aCrafting))); rList = stacks.stream() .filter( tOutput -> tOutput.stackSize == 1 && tOutput.getMaxDamage() > 0 && tOutput.getMaxStackSize() == 1) .collect(Collectors.toList()); } else for (Iterator iterator = aList.iterator(); iterator.hasNext();) { IRecipe tRecipe = iterator.next(); boolean matched = false; try { matched = tRecipe.matches(aCrafting, DW); } catch (Throwable e) { e.printStackTrace(GT_Log.err); } if (matched) { ItemStack tOutput = tRecipe.getCraftingResult(aCrafting); if (tOutput == null || tOutput.stackSize <= 0) { // Seriously, who would ever do that shit? if (!GregTech_API.sPostloadFinished) throw new GT_ItsNotMyFaultException( "Seems another Mod added a Crafting Recipe with null Output. Tell the Developer of said Mod to fix that."); continue; } if (tOutput.stackSize != 1) continue; if (tOutput.getMaxDamage() <= 0) continue; if (tOutput.getMaxStackSize() != 1) continue; if (tRecipe instanceof ShapelessRecipes) continue; if (tRecipe instanceof ShapelessOreRecipe) continue; if (tRecipe instanceof IGT_CraftingRecipe) continue; rList.add(GT_Utility.copyOrNull(tOutput)); iterator.remove(); } } return rList; } /** * Used in my own Macerator. Decreases StackSize of the Input if wanted. */ @Deprecated public static ItemStack getMaceratorOutput(ItemStack aInput, boolean aRemoveInput, ItemStack aOutputSlot) { return GT_Utility.copyOrNull( getMachineOutput(aInput, getMaceratorRecipeList(), aRemoveInput, new NBTTagCompound(), aOutputSlot)[0]); } /** * Used in my own Extractor. Decreases StackSize of the Input if wanted. */ @Deprecated public static ItemStack getExtractorOutput(ItemStack aInput, boolean aRemoveInput, ItemStack aOutputSlot) { return GT_Utility.copyOrNull( getMachineOutput(aInput, getExtractorRecipeList(), aRemoveInput, new NBTTagCompound(), aOutputSlot)[0]); } /** * Used in my own Compressor. Decreases StackSize of the Input if wanted. */ @Deprecated public static ItemStack getCompressorOutput(ItemStack aInput, boolean aRemoveInput, ItemStack aOutputSlot) { return GT_Utility.copyOrNull( getMachineOutput(aInput, getCompressorRecipeList(), aRemoveInput, new NBTTagCompound(), aOutputSlot)[0]); } /** * Used in my own Furnace. */ public static ItemStack getSmeltingOutput(ItemStack aInput, boolean aRemoveInput, ItemStack aOutputSlot) { if (aInput == null || aInput.stackSize < 1) return null; ItemStack rStack = GT_OreDictUnificator.get( FurnaceRecipes.smelting() .getSmeltingResult(aInput)); if (rStack != null && (aOutputSlot == null || (GT_Utility.areStacksEqual(rStack, aOutputSlot) && rStack.stackSize + aOutputSlot.stackSize <= aOutputSlot.getMaxStackSize()))) { if (aRemoveInput) aInput.stackSize--; return rStack; } return null; } /** * Used in my own Machines. Decreases StackSize of the Input if wanted. *

* Checks also if there is enough Space in the Output Slots. */ public static ItemStack[] getMachineOutput(ItemStack aInput, Map aRecipeList, boolean aRemoveInput, NBTTagCompound rRecipeMetaData, ItemStack... aOutputSlots) { if (aOutputSlots == null || aOutputSlots.length == 0) return new ItemStack[0]; if (aInput == null) return new ItemStack[aOutputSlots.length]; try { for (Entry tEntry : aRecipeList.entrySet()) { if (tEntry.getKey() .matches(aInput)) { if (tEntry.getKey() .getAmount() <= aInput.stackSize) { ItemStack[] tList = tEntry.getValue().items.toArray(new ItemStack[0]); if (tList.length == 0) break; ItemStack[] rList = new ItemStack[aOutputSlots.length]; rRecipeMetaData.setTag("return", tEntry.getValue().metadata); for (byte i = 0; i < aOutputSlots.length && i < tList.length; i++) { if (tList[i] != null) { if (aOutputSlots[i] == null || (GT_Utility.areStacksEqual(tList[i], aOutputSlots[i]) && tList[i].stackSize + aOutputSlots[i].stackSize <= aOutputSlots[i].getMaxStackSize())) { rList[i] = GT_Utility.copyOrNull(tList[i]); } else { return new ItemStack[aOutputSlots.length]; } } } if (aRemoveInput) aInput.stackSize -= tEntry.getKey() .getAmount(); return rList; } break; } } } catch (Throwable e) { if (D1) e.printStackTrace(GT_Log.err); } return new ItemStack[aOutputSlots.length]; } /** * Used in my own Recycler. *

* Only produces Scrap if aScrapChance == 0. aScrapChance is usually the random Number I give to the Function If you * directly insert 0 as aScrapChance then you can check if its Recycler-Blacklisted or similar */ @Nullable public static ItemStack getRecyclerOutput(ItemStack aInput, int aScrapChance) { if (aInput == null || aScrapChance != 0) return null; if (recyclerWhitelist == null) { generateRecyclerCache(); } if (recyclerWhitelist.isEmpty()) { if (searchRecyclerCache(aInput, recyclerBlacklist)) { return null; } else { return ItemList.IC2_Scrap.get(1); } } else { if (searchRecyclerCache(aInput, recyclerWhitelist)) { return ItemList.IC2_Scrap.get(1); } else { return null; } } } private static void generateRecyclerCache() { recyclerWhitelist = new HashSet<>(); for (IRecipeInput input : ic2.api.recipe.Recipes.recyclerWhitelist) { for (ItemStack stack : input.getInputs()) { recyclerWhitelist.add(GT_Utility.ItemId.create(stack.getItem(), stack.getItemDamage(), null)); } } recyclerBlacklist = new HashSet<>(); for (IRecipeInput input : ic2.api.recipe.Recipes.recyclerBlacklist) { for (ItemStack stack : input.getInputs()) { recyclerBlacklist.add(GT_Utility.ItemId.create(stack.getItem(), stack.getItemDamage(), null)); } } } private static boolean searchRecyclerCache(ItemStack stack, Set set) { if (set.contains(GT_Utility.ItemId.createWithoutNBT(stack))) { return true; } // ic2.api.recipe.RecipeInputItemStack#matches expects item with wildcard meta to accept arbitrary meta return set.contains(GT_Utility.ItemId.createAsWildcard(stack)); } /** * For the Scrapboxinator */ public static ItemStack getRandomScrapboxDrop() { return ic2.api.recipe.Recipes.scrapboxDrops.getDrop(ItemList.IC2_Scrapbox.get(1), false); } /** * Charges an Electric Item. Only if it's a valid Electric Item of course. This forces the Usage of proper Voltages * (so not the transfer limits defined by the Items) unless you ignore the Transfer Limit. If aTier is * Integer.MAX_VALUE it will ignore Tier based Limitations. * * @return the actually used Energy. */ public static int chargeElectricItem(ItemStack aStack, int aCharge, int aTier, boolean aIgnoreLimit, boolean aSimulate) { try { if (isElectricItem(aStack)) { int tTier = ((ic2.api.item.IElectricItem) aStack.getItem()).getTier(aStack); if (tTier < 0 || tTier == aTier || aTier == Integer.MAX_VALUE) { if (!aIgnoreLimit && tTier >= 0) aCharge = (int) Math.min(aCharge, V[Math.max(0, Math.min(V.length - 1, tTier))]); if (aCharge > 0) { int rCharge = (int) Math.max( 0.0, ic2.api.item.ElectricItem.manager.charge(aStack, aCharge, tTier, true, aSimulate)); return rCharge + (rCharge * 4 > aTier ? aTier : 0); } } } } catch (Throwable e) { /* Do nothing */ } return 0; } /** * Discharges an Electric Item. Only if it's a valid Electric Item for that of course. This forces the Usage of * proper Voltages (so not the transfer limits defined by the Items) unless you ignore the Transfer Limit. If aTier * is Integer.MAX_VALUE it will ignore Tier based Limitations. * * @return the Energy got from the Item. */ public static int dischargeElectricItem(ItemStack aStack, int aCharge, int aTier, boolean aIgnoreLimit, boolean aSimulate, boolean aIgnoreDischargability) { try { // if (isElectricItem(aStack) && (aIgnoreDischargability || // ((ic2.api.item.IElectricItem)aStack.getItem()).canProvideEnergy(aStack))) { if (isElectricItem(aStack)) { int tTier = ((ic2.api.item.IElectricItem) aStack.getItem()).getTier(aStack); if (tTier < 0 || tTier == aTier || aTier == Integer.MAX_VALUE) { if (!aIgnoreLimit && tTier >= 0) aCharge = (int) Math.min( aCharge, V[Math.max(0, Math.min(V.length - 1, tTier))] + B[Math.max(0, Math.min(V.length - 1, tTier))]); if (aCharge > 0) { int rCharge = (int) Math.max( 0, ic2.api.item.ElectricItem.manager.discharge( aStack, aCharge + (aCharge * 4 > aTier ? aTier : 0), tTier, true, !aIgnoreDischargability, aSimulate)); return rCharge - (rCharge * 4 > aTier ? aTier : 0); } } } } catch (Throwable e) { /* Do nothing */ } return 0; } /** * Uses an Electric Item. Only if it's a valid Electric Item for that of course. * * @return if the action was successful */ public static boolean canUseElectricItem(ItemStack aStack, int aCharge) { try { if (isElectricItem(aStack)) { return ic2.api.item.ElectricItem.manager.canUse(aStack, aCharge); } } catch (Throwable e) { /* Do nothing */ } return false; } /** * Uses an Electric Item. Only if it's a valid Electric Item for that of course. * * @return if the action was successful */ public static boolean useElectricItem(ItemStack aStack, int aCharge, EntityPlayer aPlayer) { try { if (isElectricItem(aStack)) { ic2.api.item.ElectricItem.manager.use(aStack, 0, aPlayer); if (ic2.api.item.ElectricItem.manager.canUse(aStack, aCharge)) { return ic2.api.item.ElectricItem.manager.use(aStack, aCharge, aPlayer); } } } catch (Throwable e) { /* Do nothing */ } return false; } /** * Uses an Item. Tries to discharge in case of Electric Items */ public static boolean damageOrDechargeItem(ItemStack aStack, int aDamage, int aDecharge, EntityLivingBase aPlayer) { if (GT_Utility.isStackInvalid(aStack) || (aStack.getMaxStackSize() <= 1 && aStack.stackSize > 1)) return false; if (aPlayer instanceof EntityPlayer && ((EntityPlayer) aPlayer).capabilities.isCreativeMode) return true; if (aStack.getItem() instanceof IDamagableItem) { return ((IDamagableItem) aStack.getItem()).doDamageToItem(aStack, aDamage); } else if (GT_ModHandler.isElectricItem(aStack)) { if (canUseElectricItem(aStack, aDecharge)) { if (aPlayer instanceof EntityPlayer) { return GT_ModHandler.useElectricItem(aStack, aDecharge, (EntityPlayer) aPlayer); } return GT_ModHandler.dischargeElectricItem(aStack, aDecharge, Integer.MAX_VALUE, true, false, true) >= aDecharge; } } else if (aStack.getItem() .isDamageable()) { if (aPlayer == null) { aStack.setItemDamage(aStack.getItemDamage() + aDamage); } else { aStack.damageItem(aDamage, aPlayer); } if (aStack.getItemDamage() >= aStack.getMaxDamage()) { aStack.setItemDamage(aStack.getMaxDamage() + 1); ItemStack tStack = GT_Utility.getContainerItem(aStack, true); if (tStack != null) { aStack.func_150996_a(tStack.getItem()); aStack.setItemDamage(tStack.getItemDamage()); aStack.stackSize = tStack.stackSize; aStack.setTagCompound(tStack.getTagCompound()); } else if (aStack.stackSize > 0) { aStack.stackSize--; } } return true; } return false; } /** * Uses a Soldering Iron from player or external inventory */ public static boolean useSolderingIron(ItemStack aStack, EntityLivingBase aPlayer, IInventory aExternalInventory) { if (aPlayer == null || aStack == null) return false; if (GT_Utility.isStackInList(aStack, GregTech_API.sSolderingToolList)) { if (aPlayer instanceof EntityPlayer tPlayer) { if (tPlayer.capabilities.isCreativeMode) return true; if (isElectricItem(aStack) && ic2.api.item.ElectricItem.manager.getCharge(aStack) > 1000.0d) { if (consumeSolderingMaterial(tPlayer) || (aExternalInventory != null && consumeSolderingMaterial(aExternalInventory))) { if (canUseElectricItem(aStack, 10000)) { return GT_ModHandler.useElectricItem(aStack, 10000, (EntityPlayer) aPlayer); } GT_ModHandler.useElectricItem( aStack, (int) ic2.api.item.ElectricItem.manager.getCharge(aStack), (EntityPlayer) aPlayer); return false; } else { GT_Utility.sendChatToPlayer( (EntityPlayer) aPlayer, GT_Utility.trans("094.1", "Not enough soldering material!")); } } } else { damageOrDechargeItem(aStack, 1, 1000, aPlayer); return true; } } return false; } public static boolean useSolderingIron(ItemStack aStack, EntityLivingBase aPlayer) { return useSolderingIron(aStack, aPlayer, null); } public static boolean consumeSolderingMaterial(EntityPlayer aPlayer) { if (aPlayer.capabilities.isCreativeMode) return true; IInventory tInventory = aPlayer.inventory; if (consumeSolderingMaterial(tInventory)) { if (aPlayer.inventoryContainer != null) { aPlayer.inventoryContainer.detectAndSendChanges(); } return true; } for (int i = 0; i < tInventory.getSizeInventory(); i++) { ItemStack tStack = tInventory.getStackInSlot(i); if (tStack != null && tStack.getItem() instanceof ItemToolbox) { IInventory tToolboxInventory = ((ItemToolbox) tStack.getItem()).getInventory(aPlayer, tStack); if (consumeSolderingMaterial(tToolboxInventory)) { tInventory.markDirty(); if (aPlayer.inventoryContainer != null) { aPlayer.inventoryContainer.detectAndSendChanges(); } return true; } } } return false; } /** * Consumes soldering material from given inventory */ public static boolean consumeSolderingMaterial(IInventory aInventory) { for (int i = 0; i < aInventory.getSizeInventory(); i++) { ItemStack tStack = aInventory.getStackInSlot(i); if (GT_Utility.isStackInList(tStack, GregTech_API.sSolderingMetalList)) { if (tStack.stackSize < 1) return false; if (tStack.stackSize == 1) { tStack = null; } else { tStack.stackSize--; } aInventory.setInventorySlotContents(i, tStack); aInventory.markDirty(); return true; } } return false; } /** * Is this an electric Item, which can charge other Items? */ public static boolean isChargerItem(ItemStack aStack) { try { if (isElectricItem(aStack)) { return ((ic2.api.item.IElectricItem) aStack.getItem()).canProvideEnergy(aStack); } } catch (Throwable e) { /* Do nothing */ } return false; } /** * Is this an electric Item? */ public static boolean isElectricItem(ItemStack aStack) { try { return aStack != null && aStack.getItem() instanceof ic2.api.item.IElectricItem && ((IElectricItem) aStack.getItem()).getTier(aStack) < Integer.MAX_VALUE; } catch (Throwable e) { /* Do nothing */ } return false; } public static boolean isElectricItem(ItemStack aStack, byte aTier) { try { return aStack != null && aStack.getItem() instanceof ic2.api.item.IElectricItem && ((IElectricItem) aStack.getItem()).getTier(aStack) == aTier; } catch (Throwable e) { /* Do nothing */ } return false; } /** * Returns the current charge and maximum charge of an ItemStack. * * @param aStack Any ItemStack. * @return Optional.empty() if the stack is null or not an electric item, or an Optional containing a payload of an * array containing [ current_charge, maximum_charge ] on success. */ public static Optional getElectricItemCharge(ItemStack aStack) { if (aStack == null || !isElectricItem(aStack)) { return Optional.empty(); } final Item item = aStack.getItem(); if (item instanceof final GT_MetaBase_Item metaBaseItem) { final Long[] stats = metaBaseItem.getElectricStats(aStack); if (stats != null && stats.length > 0) { return Optional.of(new Long[] { metaBaseItem.getRealCharge(aStack), stats[0] }); } } else if (item instanceof final IElectricItem ic2ElectricItem) { return Optional.of( new Long[] { (long) ic2.api.item.ElectricItem.manager.getCharge(aStack), (long) ic2ElectricItem.getMaxCharge(aStack) }); } return Optional.empty(); } /** * Allow item to be inserted into ic2 toolbox */ public static void registerBoxableItemToToolBox(ItemStack aStack) { if (aStack != null) { try { ic2.api.item.ItemWrapper.registerBoxable(aStack.getItem(), (IBoxable) sBoxableWrapper); } catch (Throwable ignored) { /* Do nothing */ } sBoxableItems.add(new GT_ItemStack(aStack)); } } @Deprecated public static void registerBoxableItemToToolBox(Item aItem) { registerBoxableItemToToolBox(new ItemStack(aItem, 1, GT_Values.W)); } public static int getCapsuleCellContainerCountMultipliedWithStackSize(ItemStack... aStacks) { int rAmount = 0; for (ItemStack tStack : aStacks) if (tStack != null) rAmount += getCapsuleCellContainerCount(tStack) * tStack.stackSize; return rAmount; } public static int getCapsuleCellContainerCount(ItemStack aStack) { if (aStack == null) return 0; if (GT_Utility.areStacksEqual(GT_Utility.getContainerForFilledItem(aStack, true), ItemList.Cell_Empty.get(1))) { return 1; } if (GT_Utility.areStacksEqual(aStack, getIC2Item("waterCell", 1, W))) { return 1; } for (OrePrefixes cellType : OrePrefixes.CELL_TYPES) { if (cellType.contains(aStack)) { return 1; } } return 0; } public static class RecipeBits { /** * Mirrors the Recipe */ public static long MIRRORED = B[0]; /** * Buffers the Recipe for later addition. This makes things more efficient. */ public static long BUFFERED = B[1]; /** * This is a special Tag I used for crafting Coins up and down. */ public static long KEEPNBT = B[2]; /** * Makes the Recipe Reverse Craftable in the Disassembler. */ public static long DISMANTLEABLE = B[3]; /** * Prevents the Recipe from accidentally getting removed by my own Handlers. */ public static long NOT_REMOVABLE = B[4]; /** * Reverses the Output of the Recipe for smelting and pulverising. */ public static long REVERSIBLE = B[5]; /** * Removes all Recipes with the same Output Item regardless of NBT, unless another Recipe Deletion Bit is added * too. */ public static long DELETE_ALL_OTHER_RECIPES = B[6]; /** * Removes all Recipes with the same Output Item limited to the same NBT. */ public static long DELETE_ALL_OTHER_RECIPES_IF_SAME_NBT = B[7]; /** * Removes all Recipes with the same Output Item limited to Shaped Recipes. */ public static long DELETE_ALL_OTHER_SHAPED_RECIPES = B[8]; /** * Removes all Recipes with the same Output Item limited to native Recipe Handlers. */ public static long DELETE_ALL_OTHER_NATIVE_RECIPES = B[9]; /** * Disables the check for colliding Recipes. */ public static long DO_NOT_CHECK_FOR_COLLISIONS = B[10]; /** * Only adds the Recipe if there is another Recipe having that Output */ public static long ONLY_ADD_IF_THERE_IS_ANOTHER_RECIPE_FOR_IT = B[11]; /** * Only adds the Recipe if it has an Output */ public static long ONLY_ADD_IF_RESULT_IS_NOT_NULL = B[12]; /** * Don't remove shapeless recipes with this output */ public static long DONT_REMOVE_SHAPELESS = B[13]; } }